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ść. int ** spr( char * filename ) { cv::Mat img = cv::imread( filename ); if( !img.data ) cout << "Nie odnaleziono pliku (funkcja readall)" << filename; int ** tab; 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 ); 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; 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 ) { 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; }
|
|
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? |
|
j23 |
» 2017-02-02 10:46:27 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 ) |
|
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. |
|
darko202 |
» 2017-02-02 12:05:00 1. jaki format pliku RGB otwierasz ? https://pl.wikipedia.org/wiki/Formaty_plik%C3%B3w_graficznych2. 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). |
|
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): 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ć: 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 ]; } }
|
|
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.
|
|
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ą: int ** spr( char * filename ) { cv::Mat img = cv::imread( filename ); if( !img.data ) cout << "Nie odnalezionu pliku (funkcja readjpg) " << filename; int ** tab; 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 ); 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; 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 ) { 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; }
|
|
« 1 » 2 3 |