Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Dostęp do wartości poszczególnych pixeli pliku graficznego

Ostatnio zmodyfikowano 2017-02-05 11:00
Autor Wiadomość
PanKowal
Temat założony przez niniejszego użytkownika
[C++] Dostęp do wartości poszczególnych pixeli pliku graficznego
» 2017-01-30 18:51:55
Witam,
chciałbym odczytywać kolory RBG plików tekstowych. Najpierw zrobiłem odczytywanie pixeli dla RBG. Później chciałem odczytywać również pixele z innych plików. I tu z pomocą przyszła biblioteka OpenCV. Mam jednak problem - dla danego pliku bmp dostaję różne wyniki w zależności od funkcji. Proszę o pomoc gdzie popełniłem błąd. Poniżej przestawiam funkcję, którą napisałem dla sprawdzania wartości w tablicy - niestety nie wszystkie pola mają tą samą wartość. Pomimo tego, że teoretycznie tab i tab2 powinny mieć tą samą zawartość.
C/C++
int ** spr( char * filename ) {
   
    cv::Mat img = cv::imread( filename );
   
    if( !img.data )
         cout << "Nie odnaleziono pliku (funkcja readall)" << filename;
   
    int ** tab; //tablica dla rgb
    tab = new int *[ img.rows ];
   
    for( int x = 0; x < img.rows; x++ )
         tab[ x ] = new int[ img.cols * 3 ];
   
    for( int i = 0; i < img.rows; i++ )
    for( int j = 0; j < img.cols; j++ )
    for( int c = 0; c < img.channels(); c++ )
         tab[ i ][ j + c ] =( int ) img.at < cv::Vec3b >( i, j )[ 2 - c ];
   
   
    int i = 0;
    FILE * f = fopen( filename, "rb" );
   
    unsigned char info[ 54 ];
    fread( info, sizeof( unsigned char ), 54, f ); // read the 54-byte header // extract image height and width from header
   
    int width = *( int * ) & info[ 18 ];
    int height = *( int * ) & info[ 22 ];
    int row_padded =( width * 3 + 3 ) &( ~3 );
    unsigned char * data = new unsigned char[ row_padded ];
    unsigned char tmp;
   
    int ** tab2; //tablica dla rgb
    tab2 = new int *[ height ];
   
    for( int x = 0; x <( height ); x++ )
         tab2[ x ] = new int[ width * 3 ];
   
    for( int i = 0; i < height; i++ ) {
        fread( data, sizeof( unsigned char ), row_padded, f );
        for( int j = 0; j < width * 3; j += 3 ) {
            // Convert (B, G, R) to (R, G, B)
            tmp = data[ j ];
            data[ j ] = data[ j + 2 ];
            data[ j + 2 ] = tmp;
           
            tab2[ i ][ j ] =( int ) data[ j ];
            tab2[ i ][ j + 1 ] =( int ) data[ j + 1 ];
            tab2[ i ][ j + 2 ] =( int ) data[ j + 2 ];
        }
       
       
    }
   
   
    int licz = 0, licz1 = 0, licz2 = 0;
    for( int i = 0; i < img.rows; i++ )
    for( int j = 0; j < img.cols; j++ ) {
        if( tab[ i ][ j ] != tab2[ i ][ j ] )
             licz++;
       
        if( tab[ i ][ j + 1 ] != tab2[ i ][ j + 1 ] )
             licz1++;
       
        if( tab[ i ][ j + 2 ] != tab2[ i ][ j + 2 ] )
             licz2++;
       
    }
   
    cout << endl << "licznik: " << licz << endl << licz1 << endl << licz2;
   
    return tab;
}
P-157130
PanKowal
Temat założony przez niniejszego użytkownika
» 2017-02-02 10:11:13
Nikt nie ma żadnych pomysłów dlaczego powyższy kod nie działa?
P-157220
j23
» 2017-02-02 10:46:27
C/C++
for( int i = 0; i < img.rows; i++ )
for( int j = 0; j < img.cols; j++ )
for( int c = 0; c < img.channels(); c++ )
     tab[ i ][ j + c ] =( int ) img.at < cv::Vec3b >( i, j )[ 2 - c ];
j powinieneś "przesuwać" co piksel, czyli trzy pozycje:
for( int j = 0; j < img.cols; j += 3 )
P-157221
PanKowal
Temat założony przez niniejszego użytkownika
» 2017-02-02 11:05:27
Niestety, ale po wprowadzeniu tej poprawki nadal nie działa. Nadal gdzieś jest jeszcze jakiś błąd.
P-157222
darko202
» 2017-02-02 12:05:00
1.
jaki format pliku RGB otwierasz ?
https://pl.wikipedia.org/wiki​/Formaty_plik%C3%B3w_graficznych

2.
A co mówi Ci technologia debugowania kodu ?
np. w pętli która przegląda i pobiera kolejne "pixele"

3.
jak patrzy się w wyszukiwanie tematu cv::imread opisane są różne problemy, które wynikały z wersji lub złego użycia.

aby cos więcej napisać opisz dokładniej Twój kod (wyrwany fragment).
 
P-157223
j23
» 2017-02-02 12:10:00
@PanKowal, Błąd wskazałem właściwy, ale rozwiązanie niepełne. To, o czym pisałem, odnosiło się do indeksowania tablicy tab, czyli przesunięcie musi być co trzy, z kolei img::at powinno być indeksowane normalnie (przesunięcie o jeden):
C/C++
for( int i = 0; i < img.rows; ++i )
for( int j = 0, k = 0; k < img.cols; j += 3, ++k )
for( int c = 0; c < img.channels(); ++c )
     tab[ i ][ j + c ] =( int ) img.at < cv::Vec3b >( i, k )[ 2 - c ];


Pętlę może nieco zoptymalizować:
C/C++
for( int i = 0; i < img.rows; ++i )
{
    int( * cols )[ 3 ] =( int( * )[ 3 ] ) tab[ i ];
   
    for( int j = 0; j < img.cols; ++j )
    {
        auto c = img.at < cv::Vec3b >( i, j );
       
        cols[ j ][ 0 ] =( int ) c[ 2 ];
        cols[ j ][ 1 ] =( int ) c[ 1 ];
        cols[ j ][ 2 ] =( int ) c[ 0 ];
    }
}
P-157225
PanKowal
Temat założony przez niniejszego użytkownika
» 2017-02-02 12:50:24
@j23, dziękuję serdecznie za pomoc. Teraz odczyt jest prawidłowy. Problem rozwiązany.


@darko202, imread pozwala mi na otwieranie różnych formatów plików graficznych. Sama funkcja "wie" jak czytać zadany format.
P-157226
PanKowal
Temat założony przez niniejszego użytkownika
» 2017-02-02 13:39:08
A jednak nie jest tak kolorowo. Niektóre wartości w tab i tab2 są różne, tzn. tab != tab2.
Kod prezentuje się następująco na chwile obecną:
C/C++
int ** spr( char * filename ) {
   
    cv::Mat img = cv::imread( filename );
   
    if( !img.data )
         cout << "Nie odnalezionu pliku (funkcja readjpg) " << filename;
   
   
    int ** tab; //tablica dla rgb
    tab = new int *[ img.rows ];
   
    for( int x = 0; x < img.rows; x++ )
         tab[ x ] = new int[ img.cols * 3 ];
   
    for( int i = 0; i < img.rows; i++ )
    for( int j = 0; j < img.cols; j++ )
         tab[ i ][ j ] = 0;
   
   
    for( int i = 0; i < img.rows; ++i ) {
        int( * cols )[ 3 ] =( int( * )[ 3 ] ) tab[ i ];
       
        for( int j = 0; j < img.cols; ++j ) {
            auto c = img.at < cv::Vec3b >( i, j );
           
            cols[ j ][ 0 ] =( int ) c[ 2 ];
            cols[ j ][ 1 ] =( int ) c[ 1 ];
            cols[ j ][ 2 ] =( int ) c[ 0 ];
        }
    }
   
   
   
   
    int i = 0;
    FILE * f = fopen( filename, "rb" );
   
    unsigned char info[ 54 ];
    fread( info, sizeof( unsigned char ), 54, f ); // read the 54-byte header
   
    // extract image height and width from header
    int width = *( int * ) & info[ 18 ];
    int height = *( int * ) & info[ 22 ];
   
    cout << " " << height << " " << width;
   
   
    int row_padded =( width * 3 + 3 ) &( ~3 );
    unsigned char * data = new unsigned char[ row_padded ];
    unsigned char tmp;
   
    int ** tab2; //tablica dla rgb
    tab2 = new int *[ height ];
   
    for( int x = 0; x <( height ); x++ )
         tab2[ x ] = new int[ width * 3 ];
   
    for( int i = 0; i < height; i++ ) {
        fread( data, sizeof( unsigned char ), row_padded, f );
        for( int j = 0; j < width * 3; j += 3 ) {
           
            // Convert (B, G, R) to (R, G, B)
            tmp = data[ j ];
            data[ j ] = data[ j + 2 ];
            data[ j + 2 ] = tmp;
           
            tab2[ i ][ j ] =( int ) data[ j ];
            tab2[ i ][ j + 1 ] =( int ) data[ j + 1 ];
            tab2[ i ][ j + 2 ] =( int ) data[ j + 2 ];
        }
    }
   
   
    int licz = 0;
    for( int i = 0; i < img.rows; ++i )
    for( int j = 0; j < img.cols; ++j )
    if(( int ) tab[ i ][ j ] !=( int ) tab2[ i ][ j ] ) {
        cout << tab[ i ][ j ] << "," << tab2[ i ][ j ] << endl;
        licz++;
    }
    cout << endl << "licznik: " << licz << endl;
   
   
    return tab;
}
P-157227
« 1 » 2 3
  Strona 1 z 3 Następna strona