您的位置:首页 > 编程语言 > C语言/C++

图像相似度检测之c++代码(24位)

2008-07-04 17:54 267 查看
下面是两点非常重要的注意事项:

1.windows 读取BMP文件是从下到上(此模式下Info.Height>0),从左到右的 2.windows 扫描BMP文件是每行以4个字节(0)为单位进行补齐,当我们处理24位位图时,要考虑此问题 例如 24位位图 宽度为 3 则实际每行内存占用位 3*24/8 + 3 字节

以下是24位 位图比较的代码,和上一篇文章的代码类似,主要是新增了BMP内存补齐检测。

//#pragma comment( linker, "/subsystem:windows" )

#include <fstream>

#include <map>

#include <string>

#include <iostream>

#include <windows.h>

using namespace std; 

typedef unsigned char uvar8;   

typedef unsigned int uvar32;   

typedef unsigned short int uvar16;   

typedef  struct  { 

	uvar8 Blue; /*蓝色所占比重*/

                     uvar8 Green; /*绿色所占比重*/

                     uvar8 Red; /*红色所占比重*/

	uvar8 Reserved;

}  Palette;

//定义bmp结构 

	uvar8 bfType[2]; /* 类型标志,总是BM */ 

typedef struct 

{ 

	uvar32 bfSize; /* 文件大小 */ 

	uvar32 bfReserved1; 

	uvar32 bfOffBits; /* 位图点阵偏移量*/ 

}HEAD; 

typedef struct 

{ 

	uvar32 biSize; /* 结构体字节总数 */ 

	uvar32 biWidth; /* 图像宽度 */ 

	uvar32 biHeight; /*图像高度 */ 

	uvar16 biPlanes; /* 必须为1 */ 

	uvar16 biBitCount; /* 每个像素所占二进制位数,可能是1,4,8或 24 */ 

	uvar32 biCompress; /*压缩方式*/ 

	uvar32 biSizeImage; /*像素点阵大小 */ 

	uvar32 biXPelsPerMeter; /* 水平像素数*/ 

	uvar32 biYPelsPerMeter; /* 垂直像素数 */ 

	uvar32 biClrUsed; /*使用的颜色数 */ 

	uvar32 biClrImportant; /*重要颜色数 */ 

}INFO; 

bool ReadBMP(string strFileUrl,uvar32* & pImgData,int& iSum)

{

	HEAD strHead; 

    INFO strInfo;

    uvar8 type[2];

	//uvar32 imdata[256][256];

	Palette Rgbquad;

	ifstream fin; 

	fin.open(strFileUrl.c_str(),ios_base::in | ios_base::binary);   

	/*以二进制读方式打开该文件,一定要二进制的!*/

	  if(!fin)

	  {

		cout<<"No this file!/n";

		return false;

	  }

	  fin.read((char*)&bfType,2);

	  fin.read((char*)&strHead,sizeof(strHead));

	  fin.read((char*)&strInfo,sizeof(strInfo));

  

	  fin.seekg(strHead.bfOffBits,ios::beg);

      if (strInfo.biBitCount == 24)

	  {

	     //pImgData = (uvar8*)pImgData;

		 pImgData = new uvar32[strInfo.biWidth*strInfo.biHeight];

	  }

	  else 

		return false;

      uvar8 varHead;

	  uvar8 varMid;

	  uvar8 varTail;

	  //Windows规定一个扫描行所占的字节数必须是   

      // 4的倍数(即以long为单位),不足的以0填充, 

      //  一个扫描行所占的字节数

      uvar32 varBytePerLine = (strInfo.biWidth * strInfo.biBitCount+31)/8;

	  varBytePerLine = varBytePerLine/4 *4;

	  uvar32 varBitPerLine = varBytePerLine * 8;

	  uvar32 varByteDistance = (varBytePerLine * 8 - strInfo.biWidth * strInfo.biBitCount)/8;

	  uvar8 * varDistance = NULL;

	  if (varByteDistance != 0)

	  varDistance = new uvar8[varByteDistance];

	  for (int i =1; i<=strInfo.biWidth * strInfo.biHeight; i++)

	  {

		  fin.read((char*)&varHead, sizeof uvar8);

		  fin.read((char*)&varMid, sizeof uvar8);

		  fin.read((char*)&varTail, sizeof uvar8);

		  //fin.read((char*)&varTmp,sizeof uvar8);

	      pImgData[i] = (uvar16)varHead *1000*1000 + (uvar16)varMid* 1000 + (uvar16)varTail;

		  //读取填补的0

		  if (varByteDistance != 0 && (i+strInfo.biWidth)%strInfo.biWidth == 0) 

		  fin.read((char*)(varDistance),varByteDistance);

	  }

           delete[] varDistance;

	  fin.close();

	  iSum = strInfo.biWidth * strInfo.biHeight;

      return true;

}

int main()

{

 uvar32 *pImgData1 =NULL ,*pImgData2 = NULL;

  int i,iSum1,iSum2;

  while(1)

  {

	  string url1;

	  string url2;

	  cout<<"cin bmp file name"<<endl;

	  cin>> url1 >> url2;

	  if(!ReadBMP(url1,pImgData1,iSum1)) exit(0);

	  if(!ReadBMP(url2,pImgData2,iSum2)) exit(0);

	  map<int,int> Map1,Map2;

	  for (i=0;i<iSum1;i++)

	  { 

	//	if (Map1.find(pImgData1[i])!=Map1.end())

			Map1[pImgData1[i]]++;

//	else

	//	Map1[pImgData1[i]] = 1;

	  }

	  for (i=0;i<iSum2;i++)

	  { 

//	if (Map2.find(pImgData2[i])!=Map2.end())

			Map2[pImgData2[i]]++;

	//	else

	//	 Map2[pImgData2[i]] = 1;

	  }

	  int iSum = 0;  

	  for (map<int,int>::iterator it = Map1.begin(); it!= Map1.end(); it++)

	  {

		  iSum += Map1[it->first] < Map2[it->first] ? Map1[it->first] 

			  : Map2[it->first];

	  }

	  double dResult = (double) iSum / iSum1 > (double) iSum / iSum2 ? (double) iSum / iSum1:(double) iSum / iSum2;

	  //-----------------

	  cout<<endl;

	  cout<<"special dots    the sum of pic1    the sum of pic2"<<endl;

	  for (map<int,int>::iterator it1 = Map1.begin(); it1!= Map1.end(); it1++)

	  {

		  cout<<it1->first<<"	"<<it1->second<<"	"<<Map2[it1->first]<<endl;

	  }

	  cout<<"******************************************"<<endl;

	  cout<<"conculsion:"<<endl;

	  cout<< "The sum of dots in Pic1: "<< iSum1<<endl;

	  cout<< "The sum of dots in Pic2: "<< iSum2<<endl;

	  cout<< "The similar dots betwwen pic1 and pic2 : "<<iSum<<endl;

	  cout<<"The rate of simliar betwwen the above two pictures:  " << dResult <<endl<<endl;

           delete[] pImgData1;

	  delete[] pImgData2;

        }

  getchar();

  return 0;

   

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: