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

下面是两点非常重要的注意事项:

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 

#include 

#include 

#include 

#include 

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"<> url1 >> url2;

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

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

	  map Map1,Map2;

	  for (i=0;i::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<::iterator it1 = Map1.begin(); it1!= Map1.end(); it1++)

	  {

		  cout<first<<"	"<second<<"	"<first]<

你可能感兴趣的:(C++)