2012-07-12 3 views
0

Je souhaite pouvoir comparer 2 images (même format) et effectuer une comparaison de niveau de bits sur ces images. 1) créer des structures pour les en-têtes.2) ouvrir les fichiers et lire le contenu à partir du décalage de données d'image à partir du marqueur SOI.3) Stockez les valeurs respectives dans un tableau 3d ou un tableau vectoriel.4) Faire une comparaison sage des éléments renvoie un résultat. J'ai réussi à le faire pour un bmp en utilisant fread() et j'ai utilisé un tableau 3d comme un conteneur avec des méthodes qui peuvent allouer et libérer de la mémoire (mais les bmp sont des images non compressées). D'une certaine manière ce processus semble beaucoup plus difficile pour les jpeg et les tiffs. Même après avoir compris le format d'en-tête de ces 2 formats, mon code dit qu'il ne peut pas lire la couleur à l'élément [45] [24] .J'ai regardé plusieurs autres options comme libjpeg et CImg mais je voudrais obtenir un point de vue avant de sauter dans une nouvelle bibliothèque.jpeg et tiff Extraction de valeur de pixel

Mon code pour bmp est la suivante: ... snip ...

unsigned char*** create3dArray(FILE **fptr1,int height,int width,int depth) 
{ 
     unsigned char*** databuff = new unsigned char **[height]; 

    // Allocate an array for each element of the first array 
    for(int x = 0; x < height; ++x) 
    { 
     databuff[x] = new unsigned char *[width]; 

     // Allocate an array of integers for each element of this array 
     for(int y = 0; y < width; ++y) 
     { 
      databuff[x][y] = new unsigned char[depth]; 

      // Specify an initial value (if desired) 
      for(int z = 0; z < depth; ++z) 
      { 
        databuff[x][y][z] = -1; 

      } 
     } 
    } 

    if ((sizeof(fheader) != 14) || (sizeof(iheader) != 40)) 
    { 
     printf("Header structs are not properly packed\n"); 
    return 0; 
    } 

    if (fread(&fheader, sizeof(fheader), 1, *fptr1) != 1) 
    { 
    printf("Couldn't read fheader.\n"); 
    return 0; 
    } 

    if (fread(&iheader, sizeof(iheader), 1, *fptr1) != 1) 
    { 
    printf("Couldn't read iheader.\n"); 
    return 0; 
} 
// uncomment to get an idea of what the headers look like. 
if ((iheader.height != height) || (iheader.width != width) || (iheader.bits != 24)) 
    { 
    printf("This only works for 512x512 24-color bitmaps\n"); 
    return 0; 
    } 



    if (fheader.offset != 54) { 
    printf("This only works if the offset is equal to 54\n"); 
    return 0; 
    } 
    for (int i = 0; i < iheader.height; i++) { 
    for (int j = 0; j < iheader.width; j++) { 
     if (fread(&databuff[i][j][0], 3, 1, *fptr1) != 1){ 
      printf("Couldn't read colors for element [%d][%d]\n", i, j); 
         return 0; 
        } 
      } 
      } 

return databuff; 
} 

template <typename Tx> 
void destroy3dArray(Tx*** myArray) 
{ 
delete[] **myArray; 
delete[] *myArray; 
delete[] myArray; 
} 

int main() 
{ 
FILE *fptr1,*fptr2;  // two file pointers one for each file. 
int count=0; 
float total_bits=0; 
float ber=0;    //variable for bit error rate 
int width,height,depth; 
cout<<"Please enter height of the image "<<endl; 
cin>>height; 
cout<<"Please enter width of the image "<<endl; 
cin>>width; 
cout<<"Please enter depth of the image. The max depth can be 3 for RGB values"<<endl; 
cin>>depth; 
char *filename = "lena512.bmp"; 
char *filename2 = "lena512_2.bmp"; 
//std::string trueBinaryDataInString[512][512][3]; 

if ((fptr1 = fopen(filename, "r")) == NULL) { 
      printf("Coulsn't open file %s for reading.\n", filename); 
      return 1; 
     } 
unsigned char*** trueArray = create3dArray(&fptr1,height,width,depth); 

for(int i=0;i<height;i++) 
{ 
    //std::cout << "Row " << i << std::endl; 
    for(int j=0;j<width;j++) 
    { 
     for(int k=0;k<depth;k++) 
     { 

      total_bits += ToBinary(trueArray[i][j][k]).length(); 

     } 
     //std::cout<<endl; 
    } 
//std::cout<<endl; 
} 
std::cout << total_bits<<endl; 
//createAnddestroy3dArray<unsigned char> MyArray; 
if ((fptr2 = fopen(filename2, "r")) == NULL) { 
      printf("Coulsn't open file %s for reading.\n", filename2); 
      return 1; 
     } 
unsigned char*** trueArray2 = create3dArray(&fptr2,height,width,depth); 
/*for(int i=0;i<512;i++) 
{ 
    std::cout << "Row " << i << std::endl; 
    for(int j=0;j<512;j++) 
    { 
     for(int k=0;k<3;k++) 
     { 
      std::cout<<" "<<ToBinary(trueArray2[i][j][k]); 
     } 
     std::cout<<endl; 
    } 
std::cout<<endl; 
} 
*/ 
/******** BIT Error Rate Calculation ******/ 
for(int i=0;i<height;i++) 
{ 
for(int j=0;j<width;j++) 
    { 
    for(int k=0;k<depth;k++) 
     { 
      if(ToBinary(trueArray[i][j][k])!= ToBinary(trueArray2[i][j][k])) 
      { 
std::cout<<ToBinary(trueArray[i][j][k])<< " " <<ToBinary(trueArray2[i] [j][k])<<endl; 
      count++; 
      } 
      else 
      continue; 
     } 
    } 
} 
ber = (count/total_bits)*100; 
std::cout<<"Bit Error Rate (BER) = "<<ber<<endl; 
destroy3dArray<unsigned char>(trueArray); //Deallocating memory for array 1 
destroy3dArray<unsigned char>(trueArray2); //Deallocating memory for array 2 
return 0; 
} 

Répondre

1

JPEG et TIFF sont des formats compressés avec peut-être un plus grand degré de liberté dans le codage des images que vous pourriez peut-être attendre.

Vous approchez donc le problème du mauvais angle. Pour prendre en charge les choix de formats d'imagerie, vous avez besoin de bibliothèques pour lire et décompresser les fichiers en bitmap, tels que RGB 24 bits ou autre chose. Il peut y avoir une conversion de l'espace colorimétrique requise car l'une des images comparées peut être décompressée en espace YUV 4: 2: 2 et l'autre en 4: 2: 0, etc.

Exploiter une bibliothèque d'images à votre choix (peut-être vous avoir des contraintes de système d'exploitation aussi) vous seriez en mesure de charger et de décompresser les fichiers en un tableau 2D de pixels de format de votre intérêt. Une fois cela fait, vous le ferez dans votre code de calcul du nombre C++ et ferez la comparaison à partir de là.

+0

Donc, je devrais d'abord convertir ces formats de fichiers en bmp. Comme pour charger un fichier jpg d'abord, puis enregistrez-le en tant que fichier bmp, puis utilisez ces fichiers. Si oui, alors le changement d'état affectera-t-il les informations d'en-tête? – user1227372

+0

Pas nécessairement pour réenregistrer en .BMP, mais c'est aussi possible. Les bibliothèques mentionnées sur les réponses vous permettent de charger et décompresser en mémoire, sans sauvegarder dans le fichier intermédiaire. Les bibliothèques vous permettent également d'accéder aux métadonnées du fichier d'origine, au cas où vous en auriez besoin. –

0

L'analyse et la gestion des variations possibles dans les fichiers JPEG et TIFF est hard. Il y a un nombre surprenant de détails: profondeur de couleur, encodage progressif, données EXIF, vignettes, - la liste continue. Profitez des bibliothèques et ne réinventez pas la roue. Utilisez libjpeg et libtiff pour charger les tampons appropriés (RGB?) Pour la comparaison.

http://www.libtiff.org/

http://www.ijg.org/

FWIW, libpng est assez bon, aussi - si vous voulez prolonger votre comparaison d'images à ce format, ainsi. http://www.libpng.org/pub/png/libpng.html

Questions connexes