我采用的比较标准是:比较2幅图片,如果屏幕上颜色不同的象素点少于20个,认为测试通过,否则为不通过。
另外象素点颜色不同的标准为:如果象素点的RGB颜色差值小于20,则认为2个象素点颜色相同,否则为不同。
写了段程序如下,明明是两个不同的图片,比较的结果却是相同。请达人帮我看下哪里出现问题了,谢谢!int CmpBmp(HBITMAP hBitmap1, HBITMAP hBitmap2)
{
UINT diff_num, h, w;
BITMAP bm1,bm2;
int r1, g1, b1, r2, g2, b2;
COLORREF col1, col2; GetObject(hBitmap1,sizeof(BITMAP),(LPVOID)&bm1);//获取位图尺寸
GetObject(hBitmap2,sizeof(BITMAP),(LPVOID)&bm2);//获取位图尺寸 if((bm1.bmHeight != bm2.bmHeight) || (bm1.bmWidth != bm2.bmWidth))
{
return 10;
} diff_num = 0; for(h = 0; h < bm1.bmHeight; h++)
{
if(diff_num > 20) break;
for(w = 0; w < bm2.bmWidth; w++)
{
hdc=GetDC(NULL); //获取设备环境句柄
hdcmem=CreateCompatibleDC(hdc); //获取内存设备环境句柄
SelectObject(hdcmem,hBitmap1); //将位图选入内存设备环境中
col1 = ::GetPixel(hdcmem,w, h);
DeleteObject(hBitmap1); //释放位图
ReleaseDC(NULL,hdc); //释放设备环境句柄
hdc=GetDC(NULL); //获取设备环境句柄
hdcmem=CreateCompatibleDC(hdc); //获取内存设备环境句柄
SelectObject(hdcmem,hBitmap2); //将位图选入内存设备环境中
col2 = ::GetPixel(hdcmem,w, h);
DeleteObject(hBitmap2); //释放位图
ReleaseDC(NULL,hdc); //释放设备环境句柄
if(col1 != col2)
{
r1 = GetRValue(col1);
r2 = GetRValue(col2);
g1 = GetGValue(col1);
g2 = GetGValue(col2);
b1 = GetBValue(col1);
b2 = GetBValue(col2);
if((abs(r1 - r2) > 20) || (abs(g1 - g2) > 20) || (abs(b1 - b2) > 20))
{
diff_num ++;
}
if(diff_num > 20) break;
}
}
}
if(diff_num > 20)
{
return 11;
}
else
{
return 12;
}

}

解决方案 »

  1.   

    其实,自己可以跟踪调试啊,比如说弄一个很小的位图,比如说第一副图的第一个像素RGB(255, 0, 0),第二副图的第一个像素RGB(200, 0, 0),等等等等,将这些像素值变成你自己心知肚明的,跟踪你代码看看哪出了问题。
      

  2.   

    我断点调试了下,发觉第一个点读进来是正确的,之后的点就不对了,显示的都是4294967295。是不是这段程序有问题啊?hdc=GetDC(NULL);    //获取设备环境句柄
    hdcmem=CreateCompatibleDC(hdc);    //获取内存设备环境句柄
    SelectObject(hdcmem,hBitmap1);    //将位图选入内存设备环境中
    col1 = ::GetPixel(hdcmem,w, h);
    DeleteObject(hBitmap1);    //释放位图
    ReleaseDC(NULL,hdc);    //释放设备环境句柄
    hdc=GetDC(NULL);    //获取设备环境句柄
    hdcmem=CreateCompatibleDC(hdc);    //获取内存设备环境句柄
    SelectObject(hdcmem,hBitmap2);    //将位图选入内存设备环境中
    col2 = ::GetPixel(hdcmem,w, h);
    DeleteObject(hBitmap2);    //释放位图
    ReleaseDC(NULL,hdc);    //释放设备环境句柄
      

  3.   

    以下代码移到循环外边去          hdc=GetDC(NULL);    //获取设备环境句柄
                hdcmem=CreateCompatibleDC(hdc);    //获取内存设备环境句柄
                SelectObject(hdcmem,hBitmap1);    //将位图选入内存设备环境中
                col1 = ::GetPixel(hdcmem,w, h);
                DeleteObject(hBitmap1);    //释放位图
                ReleaseDC(NULL,hdc);    //释放设备环境句柄
                hdc=GetDC(NULL);    //获取设备环境句柄
                hdcmem=CreateCompatibleDC(hdc);    //获取内存设备环境句柄
                SelectObject(hdcmem,hBitmap2);    //将位图选入内存设备环境中
                col2 = ::GetPixel(hdcmem,w, h);
                DeleteObject(hBitmap2);    //释放位图
                ReleaseDC(NULL,hdc);    //释放设备环境句柄
      

  4.   

    可以移啊,如3楼所说,试试这样?
    不过有个疑问
    //  hdc1 hdc2 在哪声明的?int CmpBmp(HBITMAP hBitmap1, HBITMAP hBitmap2)
    {
    UINT diff_num, h, w;
    BITMAP bm1,bm2;
    int r1, g1, b1, r2, g2, b2;
    COLORREF col1, col2; GetObject(hBitmap1,sizeof(BITMAP),(LPVOID)&bm1);//获取位图尺寸
    GetObject(hBitmap2,sizeof(BITMAP),(LPVOID)&bm2);//获取位图尺寸 if((bm1.bmHeight != bm2.bmHeight) || (bm1.bmWidth != bm2.bmWidth))
    {
    return 10;
    } //  hdc1 hdc2 在
    hdc1=GetDC(NULL);    //获取设备环境句柄
    hdcmem1=CreateCompatibleDC(hdc1);    //获取内存设备环境句柄
    SelectObject(hdcmem1,hBitmap1);    //将位图选入内存设备环境中

    hdc2=GetDC(NULL);    //获取设备环境句柄
    hdcmem2=CreateCompatibleDC(hdc2);    //获取内存设备环境句柄
    SelectObject(hdcmem2,hBitmap2);    //将位图选入内存设备环境中

    diff_num = 0; for(h = 0; h < bm1.bmHeight; h++)
    {
    if(diff_num > 20) break;
    for(w = 0; w < bm2.bmWidth; w++)
    {
    col1 = ::GetPixel(hdcmem,w, h);
    col2 = ::GetPixel(hdcmem,w, h);
    if(col1 != col2)
    {
    r1 = GetRValue(col1);
    r2 = GetRValue(col2);
    g1 = GetGValue(col1);
    g2 = GetGValue(col2);
    b1 = GetBValue(col1);
    b2 = GetBValue(col2);
    if((abs(r1 - r2) > 20) || (abs(g1 - g2) > 20) || (abs(b1 - b2) > 20))
    {
    diff_num ++;
    }
    if(diff_num > 20) break;
    }
    }
    }
    if(diff_num > 20)
    {
    return 11;
    }
    else
    {
    return 12;
    } DeleteObject(hBitmap1);    //释放位图
    ReleaseDC(NULL,hdc1);    //释放设备环境句柄 DeleteObject(hBitmap2);    //释放位图
    ReleaseDC(NULL,hdc2);    //释放设备环境句柄
    }
      

  5.   

    嘿嘿,错了个地方 col1 = ::GetPixel(hdcmem1,w, h);
    col2 = ::GetPixel(hdcmem2,w, h);
      

  6.   

    应该计算所有不同的点,返回diff_num/nWidth*nHeight,可以认为大致有几成相适度
      

  7.   

    你这个是不是用来摄像头运动侦测的?
    那个需要2个阈值,我以前是这样设置的:1.对应像素(灰度8bit)差>30算该像素有变化2.(变化像素数/总像素)>0.0001算有运动,晚上这个值设为0.01红外摄像机要低些
      

  8.   

    咳..问题很简单,自己看,哈哈:for(h = 0; h < bm1.bmHeight; h++)
        {
            if(diff_num > 20) break;
            for(w = 0; w < bm2.bmWidth; w++)
            {
                hdc=GetDC(NULL);    //获取设备环境句柄
                hdcmem=CreateCompatibleDC(hdc);    //获取内存设备环境句柄
                SelectObject(hdcmem,hBitmap1);    //将位图选入内存设备环境中
                col1 = ::GetPixel(hdcmem,w, h);
                DeleteObject(hBitmap1);    //释放位图 <<== 把这个Del了还怎么比较呢  -_-".. hBitamp2也惨遭毒手.. haha
                ReleaseDC(NULL,hdc);    //释放设备环境句柄
                hdc=GetDC(NULL);    //获取设备环境句柄
                hdcmem=CreateCompatibleDC(hdc);    //获取内存设备环境句柄
              .....
             ,,
    ok..gl`
      

  9.   

    在双重循环里面这么多的GUI操作,这样的程序效率是没有啦。
    建议取两个位图的数据缓存直接进行比较。
    以24位真彩BMP为例:14字节的BITMAPFILEHEADER,40字节的BITMAPINFOHEADER数据,后面就是像素值,按B、G、R顺序存放。
    大家为什么都喜欢这样处理BMP呢?看来书本害人不浅。
      

  10.   

    是啊,直接比较文件多简单,非要用DC来比较,又麻烦又没效率,比较文件的,只要一个BYTE*就可以了,24位的后移三每次,32位图后移四,只需在内存开辟一个nWidth*nHeight*位数/8 大小的内存,然后把图像读进去就可以了
      

  11.   

    为简单起见,24位真彩位图,一样大的两个BMP文件。//打开两个文件
    CFile f1,f2; 
    int nFl;
    f1.Open(_T("文件1"),CFile::modeRead);
    f2.Open(_T("文件2"),CFile::modeRead);
    nFl = f1.GetLength();//两个图像缓冲区
    BYTE * buf1 = new BYTE[nFl - 54 +1];
    BYTE * buf2 = new BYTE[nFl - 54 +1];//文件头和信息头,假设两个文件时是一样的,只留一个文件的就可以
    BITMAPFILEHEADER biFileHdr;
    BITMAPINFOHEADER biInfoHdr;
    f1.Read(&biFileHdr,sizeof(BITMAPFILEHEADER));
    f2.Read(&biFileHdr,sizeof(BITMAPFILEHEADER));
    f1.Read(&biInfoHdr,sizeof(BITMAPINFOHEADER));
    f2.Read(&biInfoHdr,sizeof(BITMAPINFOHEADER));//在biInfoHdr里面找宽度高度等图像信息
    f1.Read(buf1,nFl - 54); 
    f2.Read(buf2,nFl - 54); 
    f1.Close();
    f2.Close();//现在两个BMP文件已经分别在buf1和buf2里面了,3个字节一个像素,按BGR顺序排列
    //开始比较吧delete [] buf1;
    delete [] buf1;54是 sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)