2019-07-10

                                                                   对比两张图片是不是一样的(点、区域)

原理:读取两张图片相同坐标的RGB像素,将图片的RGB值与参照物图片的RGB值做对比。

相似度= (相同像素/ (icon_width * icon_height) * 100)

相同像素:两张图片的同一坐标的RGB值一样。

图片中坐标与RGB值的映射关系:

假设图片大小:1920*  720、 X坐标、Y坐标;

代码中BMP图片的规范为4通道32bit;

某个点的RGB:首地址+ X * 4 + Y * 1920 * 4

bitmapdf.h:

#define RETURN_SUCCESS 1

#define  RETURN_ERROR            0

typedef      long                          LONG;

typedef      unsigned char      BYTE;

typedef      unsigned short    WORD;

typedef      unsigned long      DWORD;

/*Bitmap data structures*/

typedef struct  BITMAP

{

  DWORD    biSize;                    //bitmap size

  LONG        biWidth;                //bitmap width

  LONG        biHeight;                //bitmap height

  WORD        biPlanes;

  WORD        biBitCount;            //bit depth

  DWORD    biCompression;

  DWORD    biSizeImage;

  LONG        biXPelsPerMeter;  //horizontal resolution

  LONG        biYPelsPerMeter;  //vertical resolution

  DWORD    biClrUsed;

  DWORD    biClrImportant;

}BITMAPINFOHEADER;

typedef  struct RGB

{

BYTE    byR;

BYTE    byG;

BYTE    byB;

}BITMAPRGB;

typedef enum

{

BM_BLACKSCREEN_PATH = 0,  //黑屏位图

BM_LAMPMONITO_PATH = 1,    //指示灯监视位图

}BITMAP_FILE_PATH;

#define    BM_BLACKSCREEN_PATH_              "/tmp/ScreenShot.bmp"

#define    BM_LAMPMONITO_PATH_              "/tmp/LampMonitor.bmp"

#define    BM_REFERENCE_PATH_                  "/data/LampReference.bmp"      //Used as a reference (The indicator light to be monitored must be kept on)

typedef struct

{

int  iCoordinate_X;

int  iCoordinate_Y;

int  iIconWidth;

int  iIconHeight;

}StBitmapCfgInfo;

CBitmap.h:

class CBitmap {

public:

CBitmap();

virtual ~CBitmap();

public:

int    ReadReferenceBitmap(const  char  *szFileName);

int    ReadCompareBitmap(const char  *szFileName);

int    GetBitmapRGB2Compare(StBitmapCfgInfo stCfg);

public:

BYTE    *m_byBufReference;            /*Storage indicator normally displays data*/

BYTE    *m_byBufCompare;            /*Store images for comparison*/

LONG    m_LineByteWidth[2];        /* biWidth * (biBitCount  /  8)*/

BITMAPINFOHEADER  m_stBitmapReference;

BITMAPINFOHEADER  m_stBitmapCompare;

};

CBitmap.cpp

CBitmap::CBitmap() {

// TODO Auto-generated constructor stub

m_byBufReference = NULL;

m_byBufCompare = NULL;

}

CBitmap::~CBitmap() {

// TODO Auto-generated destructor stub

}

int  CBitmap::ReadReferenceBitmap(const  char  *szFileName)

{

FILE    *file;

WORD  bfh[7];

LONG  dpixeladd;    //bit depth

if (NULL == (file = fopen(szFileName, "rb")))

{

LOGWAR("open normal bitmap file falied");

return RETURN_ERROR;

}

fread(&bfh, sizeof(WORD), 7, file);

if (bfh[0] != (WORD)(((WORD)'B')|('M'<<8)))

{

LOGWAR("read bitmap head failed");

fclose(file);

return  RETURN_ERROR;

}

fread(&m_stBitmapReference, sizeof(BITMAPINFOHEADER), 1, file);

if(m_stBitmapReference.biBitCount < 24)

{

LOGWAR("Bitmap bitdepth does not meet requirements");

fclose(file);

return  RETURN_ERROR;

}

/*The number of bytes required for a pixel

* Four bytes represent one pixel*/

dpixeladd = m_stBitmapReference.biBitCount  /  8;

m_LineByteWidth[0] = m_stBitmapReference.biWidth  *  dpixeladd;

if ((m_LineByteWidth[0] % 4) != 0)

{

m_LineByteWidth[0] += 4 - (m_LineByteWidth[0] % 4);

}

if ((m_byBufReference = (BYTE*)malloc(sizeof(BYTE)* m_LineByteWidth[0] * abs(m_stBitmapReference.biHeight))) != NULL)

{

fread(m_byBufReference, m_LineByteWidth[0] * abs(m_stBitmapReference.biHeight), 1, file);

fclose(file);

return  RETURN_SUCCESS;

}

fclose(file);

return RETURN_ERROR;

}

int  CBitmap::ReadCompareBitmap(const char  *szFileName)

{

FILE    *file;

WORD  bfh[7];

LONG  dpixeladd;    //bit depth

if (NULL == (file = fopen(szFileName, "rb")))

{

LOGWAR("open normal bitmap file falied");

return RETURN_ERROR;

}

fread(&bfh, sizeof(WORD), 7, file);

if (bfh[0] != (WORD)(((WORD)'B')|('M'<<8)))

{

LOGWAR("read bitmap head failed");

fclose(file);

return  RETURN_ERROR;

}

fread(&m_stBitmapCompare, sizeof(BITMAPINFOHEADER), 1, file);

if(m_stBitmapCompare.biBitCount < 24)

{

LOGWAR("Bitmap bitdepth does not meet requirements");

fclose(file);

return  RETURN_ERROR;

}

/*The number of bytes required for a pixel

* Four bytes represent one pixel*/

dpixeladd = m_stBitmapCompare.biBitCount  /  8;

m_LineByteWidth[1] = m_stBitmapCompare.biWidth  *  dpixeladd;

if ((m_LineByteWidth[1] % 4) != 0)

{

m_LineByteWidth[1] += 4 - (m_LineByteWidth[1] % 4);

}

if ((m_byBufCompare = (BYTE*)malloc(sizeof(BYTE)* m_LineByteWidth[1] * abs(m_stBitmapCompare.biHeight))) != NULL)

{

fread(m_byBufCompare, m_LineByteWidth[1] * abs(m_stBitmapCompare.biHeight), 1, file);

fclose(file);

return  RETURN_SUCCESS;

}

fclose(file);

return RETURN_ERROR;

}

int    CBitmap::GetBitmapRGB2Compare(StLampMonitorCfgInfo  stLampCfg, int  iID)

{

if(stLampCfg.iCoordinate_X < 0

|| stLampCfg.iCoordinate_X > m_stBitmapReference.biWidth

|| stLampCfg.iCoordinate_Y < 0

|| stLampCfg.iCoordinate_Y > abs(m_stBitmapReference.biHeight)

|| stLampCfg.iIconWidth < 0

|| stLampCfg.iIconWidth > m_stBitmapReference.biWidth

|| stLampCfg.iIconHeight < 0

|| stLampCfg.iIconHeight > abs(m_stBitmapReference.biHeight))

{

LOGWAR("Bitmap coordinates are not in range");

return RETURN_ERROR;

}

int  iTempX;

int  iTempY;

int  dpixeladd;

int  iTotalPixels;

int  iSamePixels = 0;

float  iSimilarity;

BYTE  *pBufReference;

BYTE  *pBufCompare;

BITMAPRGB  stRGB[2];

dpixeladd  =  m_stBitmapReference.biBitCount  /  8;

if(dpixeladd != 4)

{

LOGWAR("Invalid bitmap");

return RETURN_ERROR;

}

iTotalPixels  =  stLampCfg.iIconWidth  *  stLampCfg.iIconHeight;

for(iTempX = stLampCfg.iCoordinate_X; iTempX < stLampCfg.iCoordinate_X + stLampCfg.iIconWidth; iTempX++)

{

for(iTempY = stLampCfg.iCoordinate_Y; iTempY < stLampCfg.iCoordinate_Y + stLampCfg.iIconHeight; iTempY++)

{

/*坐标与像素的映射关系:指针首地址 + iTempX * 4 + iTempY * 1920 * 4

iTempX:要比较像素的x坐标

dpixeladd: 32 / 8, 一个像素占用4个字节 B  G  R  A

iTempY * m_LineByteWidth: 1920 * 4 * Y  (列 * 行的指针偏移) */

/* The indicator normally displays */

pBufReference = m_byBufReference + iTempX * dpixeladd + iTempY * m_LineByteWidth[0];

stRGB[0].byB = *pBufReference;

stRGB[0].byG = *(pBufReference + 1);

stRGB[0].byR = *(pBufReference + 2);

/*Whether the indicator is displayed */

pBufCompare = m_byBufCompare + iTempX * dpixeladd + iTempY * m_LineByteWidth[1];

stRGB[1].byB = *pBufCompare;

stRGB[1].byG = *(pBufCompare + 1);

stRGB[1].byR = *(pBufCompare + 2);

/*printf("stRGB[0].byB = %d stRGB[1].byB = %d, stRGB[0].byG = %d stRGB[1].byG = %d, stRGB[0].byR = %d stRGB[1].byR = %d \n",

                                                                                                                                                                                                  stRGB[0].byB,

                                                                                                                                                                                                  stRGB[1].byB,

                                                                                                                                                                                                  stRGB[0].byG,

                                                                                                                                                                                                  stRGB[1].byG,

                                                                                                                                                                                                  stRGB[0].byR,

                                                                                                                                                                                                  stRGB[1].byR);*/

/* RGB compare */

if((stRGB[0].byB == stRGB[1].byB) && (stRGB[0].byG == stRGB[1].byG) && (stRGB[0].byR == stRGB[1].byR))

{

iSamePixels++;

}

}

}

/*If the similarity is greater than 80%, the indicator is normally displayed */

iSimilarity = ((float)iSamePixels / (float)iTotalPixels) * 100;

LOGDBG("iTotalPixels = %d, iSamePixels = %d, iSimilarity = %f",iTotalPixels, iSamePixels, iSimilarity);

printf("iTotalPixels = %d, iSamePixels = %d, iSimilarity = %f \n",iTotalPixels, iSamePixels, iSimilarity);

if(iSimilarity < 90)

{

LOGERR("error: Indicator light is not showing: %d", iID);

}

free(m_byBufReference), m_byBufReference = NULL;

free(m_byBufCompare), m_byBufCompare = NULL;

return RETURN_SUCCESS;

}

main.c:

int main(int argc, char *argv[])

{

CBitmap  objBitmap;

StBitmapCfgInfo objStMap;

//对比图片的某个矩形区域

objStMap.iCoordinate_X = 10;

objStMap.iCoordinate_Y = 10;

objStMap.iIconWidth= 50;

objStMap.iIconHeight= 50;

if(!objBitmap.ReadReferenceBitmap(BM_REFERENCE_PATH_))

{

LOGWAR ("ReadReferenceBitmap error. ");

return;

}

if(!objBitmap.ReadCompareBitmap(BM_LAMPMONITO_PATH_))

{

LOGWAR ("ReadCompareBitmap error. ");

return;

}

objBitmap.GetBitmapRGB2Compare(objStMap);

}

你可能感兴趣的:(2019-07-10)