0

我希望能够比较 2 个图像(相同格式)并对这些图像执行位级比较。1)为标题创建结构。2)打开文件并读取从 SOI 标记的图像数据偏移开始的内容。3)将各自的值存储在 3d 数组或向量数组中。4)进行元素比较和返回一个结果。我已经成功地能够使用 fread() 为 bmp 执行此操作,并将 3d 数组用作容器,其中包含可以分配和取消分配内存的方法。(但 bmp 是未压缩的图像)。不知何故,这个过程对于 jpeg 和 tiff 来说似乎要困难得多。即使在理解了这两种格式的标题格式之后,我的代码也说它无法读取元素 [45][24] 的颜色。

我的 bmp 代码如下: ...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;
 }
4

2 回答 2

1

JPEG 和 TIFF 是压缩格式,在编码图像时可能具有您可能期望的更大自由度。

所以你从错误的角度来处理问题。为了支持图像格式的选择,您需要库来读取文件并将其解压缩为位图,例如 24 位 RGB 或其他格式。可能需要进行色彩空间转换,因为其中一张比较图像可能被解压缩为 4:2:2 YUV 空间,另一张为 4:2:0 等。

利用您选择的一些图像库(也许您也有操作系统限制),您将能够将文件加载和解压缩为您感兴趣的像素格式的二维数组。完成后,您会将其输入您的 C++ 数字运算代码并从那里进行比较。

于 2012-07-12T20:49:18.343 回答
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

于 2012-07-12T21:44:14.513 回答