2012-07-12 78 views
0

我想能够比较2个图像(相同格式)并对这些图像执行比特级比较。 1)为标题创建结构.2)打开文件并从SOI标记的图像数据偏移处开始读取内容.3)将相应值存储在3d数组或向量数组中.4)进行元素明智的比较,返回结果。我已经成功地使用fread()为bmp做了这个工作,并且使用了一个3d数组作为容器,并使用可以分配和释放内存的方法(但是bmp是未压缩的图像)。不知何故,这个过程对jpeg和tiff来说似乎要困难得多。即使理解了这两种格式的标题格式,我的代码却说它不能读取元素[45] [24]的颜色。我看过其他几个选项,比如libjpeg和CImg,但我希望在跳入新图书馆之前获得观点。jpeg和tiff像素值提取

我对BMP代码如下: ...喀嚓...

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; 
} 

回答

1

JPEG和TIFF压缩与也许更大的自由度格式编码,你或许会想到的图像。

因此,您正从错误的角度接近问题。为了支持成像格式的选择,您需要库来读取文件并将其解压缩为位图,例如24位RGB或其他。可能需要进行颜色空间转换,因为其中一个比较图像可能会被解压缩到4:2:2 YUV空间,另一个则是4:2:0等。

利用您选择的某个图像库也有操作系统的限制),你将能够加载和解压缩文件为您感兴趣的二维像素格式。完成这些之后,您会将其填充到您的C++数字处理代码中,并从那里进行比较。

+0

所以我必须首先将这些文件格式转换成bmp的。如先载入jpg,然后将其保存为bmp,然后使用这些文件。如果是,那么状态的改变是否会影响任何标题信息? – user1227372 2012-07-12 21:23:27

+0

不一定要重新保存到.BMP中,这也是可能的。答案中提到的库允许您在内存中加载和解压缩,而不保存到中间文件中。这些库还允许您访问原始文件的元数据,以备需要时使用。 – 2012-07-12 22:21:34

0

成功解析并处理JPEG和TIFF文件中的可能变化是。有一个令人惊讶的数量的细节:颜色深度,渐进式编码,EXIF数据,缩略图, - 列表继续。利用这些库,不要重新发明轮子。使用libjpeg和libtiff加载合适的(RGB?)缓冲区进行比较。

http://www.libtiff.org/

http://www.ijg.org/

FWIW,libpng的是相当不错的,太 - 如果你想扩展您的图像比较,以这种格式,以及。 http://www.libpng.org/pub/png/libpng.html