minghan0313 发表于 2010-9-4 16:23

大家来找茬图片对比问题 容错算法怎么写才合适?

自己刚学C++没多长时间  想自己写一个大家来找茬的辅助工具   对算法也不清楚  对图像学也不是很明白

先写了一个验证自己算法的小程序FindDifferences   我把QQ大家来找茬全屏后截了几张图片  FindDifferences所作的工作就是读取截屏bmp文件  对比截屏中两张找茬图片   找出不一样的地方   思路很简单  用GetPixel得到两个图片位置中相对位置的点的COLORREF值   如果不一样,就将两张中的一张图片中的这个点用纯色覆盖    有了想法就去写了    写出来之后运行  结果惨不忍睹   两张图片中没有几处地方是全相等的  

************************************************************************************************
这里有一个问题  是否找茬游戏中的两张图片不可能除了找茬的位置之外COLOOREF完全相等?
************************************************************************************************

之后有人提醒我要有一定的容错率    因为没有接触过图形学  怎么容错不清楚   就去网上找了一下资料   有一个公式 sqrt(absR*absR+absG*absG+absB*absB)>100   具体原理我不懂   我就拿来用了   结果还算可以   但是容错的范围是随时要改的   

***************************************************************************************************************
这里是第二个问题   两张图片对比是不是不能用GetPixel得到COLORREF来对比是否相等  必须要有容错率?
***************************************************************************************************************

对算法一筹莫展的时候去网上找了一个已经做好的QQ大家来找茬的辅助工具,不管窗口是否最小化,分辨率如何,找得都很精准,唉,信心倍受打击啊  

***************************************************************************************************************
这里是第三个问题    是不是这种辅助程序不能用简单的对比颜色  还要涉及内存问题?
***************************************************************************************************************

下面是程序效果图:
[attach]52949[/attach]
[attach]52950[/attach]


[[i] 本帖最后由 minghan0313 于 2010-9-4 16:31 编辑 [/i]]

minghan0313 发表于 2010-9-4 16:25

二楼贴上源代码

[code][color=#0000FF]#include[/color] [color=#800000]<windows.h>[/color]
[color=#0000FF]#include[/color] [color=#800000]<math.h>[/color]
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

[color=#0000FF]int[/color] WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR LpcmdLine,[color=#0000FF]int[/color] nCmdShow){
    [color=#0000FF]static[/color] TCHAR szAppName[]=TEXT([color=#800000]"[/color][color=#800000]Painter[/color][color=#800000]"[/color]);
    [color=#0000FF]static[/color] TCHAR szClassName[]=TEXT([color=#800000]"[/color][color=#800000]PainterClass[/color][color=#800000]"[/color]);
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style=CS_HREDRAW | CS_VREDRAW;[color=#008000]//[/color][color=#008000]风格[/color][color=#008000]
[/color]    wndclass.lpfnWndProc=WndProc;[color=#008000]//[/color][color=#008000]*重要*long point to function 指向函数的的长指针 基于该窗口类创建的窗口所使用的窗口函数的入口地址[/color][color=#008000]
[/color]    wndclass.cbClsExtra=[color=#800080]0[/color];[color=#008000]//[/color][color=#008000]预留额外空间[/color][color=#008000]
[/color]    wndclass.cbWndExtra=[color=#800080]0[/color];[color=#008000]//[/color][color=#008000]预留额外空间[/color][color=#008000]
[/color]    wndclass.hInstance=hInstance;[color=#008000]//[/color][color=#008000]所在程序的实例句柄[/color][color=#008000]
[/color]    wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);[color=#008000]//[/color][color=#008000]图标[/color][color=#008000]
[/color]    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);[color=#008000]//[/color][color=#008000]图标[/color][color=#008000]
[/color]    wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);[color=#008000]//[/color][color=#008000]背景色[/color][color=#008000]
[/color]    wndclass.lpszMenuName=NULL;[color=#008000]//[/color][color=#008000]指定窗口类的菜单[/color][color=#008000]
[/color]    wndclass.lpszClassName=szClassName;[color=#008000]//[/color][color=#008000]窗口类类名[/color][color=#008000]
[/color]    [color=#0000FF]if[/color] (!RegisterClass(&wndclass))[color=#008000]//[/color][color=#008000]注册窗口类 需要一个指向windclass的指针[/color][color=#008000]
[/color]    {
        MessageBox(NULL,TEXT([color=#800000]"[/color][color=#800000]This program requires Windows NT![/color][color=#800000]"[/color]),szAppName,MB_ICONERROR);
        [color=#0000FF]return[/color] [color=#800080]0[/color];
    }
    hwnd=CreateWindow(szClassName,[color=#008000]//[/color][color=#008000]窗口类名称[/color][color=#008000]
[/color]        TEXT([color=#800000]"[/color][color=#800000]Painter[/color][color=#800000]"[/color]),[color=#008000]//[/color][color=#008000]窗口标题[/color][color=#008000]
[/color]        WS_OVERLAPPEDWINDOW,[color=#008000]//[/color][color=#008000]窗口显示风格[/color][color=#008000]
[/color]        CW_USEDEFAULT,[color=#008000]//[/color][color=#008000]初始x方向位置[/color][color=#008000]
[/color]        CW_USEDEFAULT,[color=#008000]//[/color][color=#008000]初始y方向位置[/color][color=#008000]
[/color]        CW_USEDEFAULT,[color=#008000]//[/color][color=#008000]初始x方向大小[/color][color=#008000]
[/color]        CW_USEDEFAULT,[color=#008000]//[/color][color=#008000]初始y方向大小[/color][color=#008000]
[/color]        NULL,[color=#008000]//[/color][color=#008000]父窗口句柄[/color][color=#008000]
[/color]        NULL,[color=#008000]//[/color][color=#008000]菜单句柄[/color][color=#008000]
[/color]        hInstance,[color=#008000]//[/color][color=#008000]程序实例句柄[/color][color=#008000]
[/color]        NULL);[color=#008000]//[/color][color=#008000]创建参数 可以访问以后想要引用的程序中的数据[/color][color=#008000]
[/color]    nCmdShow=SW_SHOWMAXIMIZED;
    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);
    [color=#0000FF]while[/color] (GetMessage(&msg,NULL,[color=#800080]0[/color],[color=#800080]0[/color]))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    [color=#0000FF]return[/color] ([color=#0000FF]int[/color])msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    [color=#0000FF]static[/color] [color=#0000FF]int[/color] cxClient,cyClient,cxBitmap,cyBitmap;
    [color=#0000FF]static[/color] HINSTANCE hInstance;
    [color=#0000FF]static[/color] BITMAP bmp;
    [color=#0000FF]static[/color] HANDLE h;[color=#008000]//[/color][color=#008000]bmp图片句柄[/color][color=#008000]
[/color]    [color=#0000FF]static[/color] HDC hdc,hdcMemImag;[color=#008000]//[/color][color=#008000]hdcMemImag是与窗口DC兼容的DC[/color][color=#008000]
[/color]   

   

     h=LoadImage(NULL,L[color=#800000]"[/color][color=#800000]C:\\3333.bmp[/color][color=#800000]"[/color],IMAGE_BITMAP,[color=#800080]0[/color],[color=#800080]0[/color],LR_LOADFROMFILE);
     GetObject(h,[color=#0000FF]sizeof[/color](BITMAP),&bmp);[color=#008000]//[/color][color=#008000]得到图片的宽,高等信息,储存在bmp对象*/[/color][color=#008000]
[/color]   

    [color=#0000FF]switch[/color](message)
    {
    [color=#0000FF]case[/color] WM_CREATE:
        COLORREF colleft,colright;[color=#008000]//[/color][color=#008000]colleft 左边图片的像素点  colright 右边图片的像素点[/color][color=#008000]
[/color]        [color=#0000FF]int[/color] leftR,rightR,leftG,rightG,leftB,rightB,absR,absG,absB;
        hdc=GetDC(hwnd);[color=#008000]//[/color][color=#008000]得到窗口的DC(hWnd是窗口句柄)[/color][color=#008000]
[/color]        hdcMemImag=CreateCompatibleDC(hdc);[color=#008000]//[/color][color=#008000]得到与窗口DC兼容的DC[/color][color=#008000]
[/color]        SelectObject(hdcMemImag,h);[color=#008000]//[/color][color=#008000]把得到的DC与图片句柄关联起来[/color][color=#008000]
[/color]        [color=#0000FF]for[/color] ([color=#0000FF]int[/color] y=[color=#800080]192[/color];y<=[color=#800080]639[/color];y++) [color=#008000]//[/color][color=#008000]坐标是之前已经找好的[/color][color=#008000]
[/color]        {   

            [color=#0000FF]for[/color] ([color=#0000FF]int[/color] x=[color=#800080]8[/color];x<=[color=#800080]505[/color];x++)
            {
                colleft=GetPixel(hdcMemImag,x,y);[color=#008000]//[/color][color=#008000]获得左边图片的像素点[/color][color=#008000]
[/color]                colright=GetPixel(hdcMemImag,x+[color=#800080]508[/color],y);[color=#008000]//[/color][color=#008000]获得右边图片的像素点[/color][color=#008000]
[/color]               

                leftR=GetRValue(colleft);
                leftG=GetGValue(colleft);
                leftB=GetBValue(colleft);
                rightR=GetRValue(colright);
                rightG=GetGValue(colright);
                rightB=GetBValue(colright);
                absR=leftR-rightR;
                absG=leftG-rightG;
                absB=leftB-rightB;
                [color=#0000FF]if[/color] (sqrt((DOUBLE)(absR*absR+absG*absG+absB*absB))>[color=#800080]45[/color])
                {
                    SetPixel(hdcMemImag,x+[color=#800080]508[/color],y,RGB([color=#800080]0[/color],[color=#800080]255[/color],[color=#800080]0[/color]));
                }
            }
        }
        ReleaseDC(hwnd,hdc);[color=#008000]//[/color][color=#008000]释放GetDC得到的DC[/color][color=#008000]
[/color]        [color=#0000FF]break[/color];
    [color=#0000FF]case[/color] WM_SIZE:
        InvalidateRect(hwnd,NULL,TRUE);
        [color=#0000FF]break[/color];
    [color=#0000FF]case[/color] WM_PAINT:

        hdc=GetDC(hwnd);[color=#008000]//[/color][color=#008000]得到窗口的DC(hWnd是窗口句柄)[/color][color=#008000]
[/color]        BitBlt(hdc,[color=#800080]0[/color],[color=#800080]0[/color],bmp.bmWidth,bmp.bmHeight,hdcMemImag,[color=#800080]0[/color],[color=#800080]0[/color],SRCCOPY);[color=#008000]//[/color][color=#008000]把图片画在窗体上[/color][color=#008000]
[/color]        ReleaseDC(hwnd,hdc);

        [color=#0000FF]break[/color];
    [color=#0000FF]case[/color] WM_DESTROY:
        PostQuitMessage([color=#800080]0[/color]);
        [color=#0000FF]break[/color];
    }
    [color=#0000FF]return[/color] DefWindowProc(hwnd,message,wParam,lParam);
}[/code]

vfdff 发表于 2010-9-5 03:41

sqrt(absR*absR+absG*absG+absB*absB)>100  这个是因为三基色的原理吧

vfdff 发表于 2010-9-5 03:56

根据图像学原理,我感觉两个图像相减后作均值滤波,然后设置一个阀值应该能找出两者的不同点

minghan0313 发表于 2010-9-5 10:36

[quote][b]以下是引用[u]vfdff[/u]在2010-9-5 03:56:07的发言:[/b]

根据图像学原理,我感觉两个图像相减后作均值滤波,然后设置一个阀值应该能找出两者的不同点[/quote]额...听上去好复杂啊   昨天看了一本数字图像处理的书   感觉跟看高数书是的....

迷失的木桶 发表于 2010-9-5 18:40

不需要很复杂,给个提示,,“位操作”

minghan0313 发表于 2010-9-6 08:57

[quote][b]以下是引用[u]迷失的木桶[/u]在2010-9-5 18:40:29的发言:[/b]

不需要很复杂,给个提示,,“位操作”[/quote]希望这位前辈能多多指点一下

迷失的木桶 发表于 2010-9-6 20:10

1001000
0111110
--------
1110110

看出上面是什么位操作了吗?
发挥你的想象。

黑白世界 发表于 2010-9-14 08:37

程序算法蛮好的
简单明了
我试验了下
找的很正确[em01]


[[i] 本帖最后由 黑白世界 于 2010-9-14 21:41 编辑 [/i]]

minghan0313 发表于 2010-9-17 17:40

[quote][b]以下是引用[u]黑白世界[/u]在2010-9-14 08:37:43的发言:[/b]

程序算法蛮好的
简单明了
我试验了下
找的很正确[em01]
[/quote]楼上说的是我写的算法吗?

我自己用别的找茬游戏试验了一次  的确找得很准  不同的地方能标示得很精确   但是在QQ上的大家来找茬上不是很精准   颜色快的边缘也会被标示出来

迷失的木桶 发表于 2010-9-18 00:11

像楼主一样,我也写过QQ找茬的辅助程序,QQ找茬游戏有一种简单的防作弊算法,因此通过简单判断两个像素是否相同是不准确的。
就像楼主那样找出很多不重要的不同点。



黑白世界 发表于 2010-9-18 09:58

[quote][b]以下是引用[u]迷失的木桶[/u]在2010-9-18 00:11:02的发言:[/b]

像楼主一样,我也写过QQ找茬的辅助程序,QQ找茬游戏有一种简单的防作弊算法,因此通过简单判断两个像素是否相同是不准确的。
就像楼主那样找出很多不重要的不同点。



[/quote]你有什么好办法 说来听听
谢谢

minghan0313 发表于 2010-9-20 10:16

[quote][b]以下是引用[u]迷失的木桶[/u]在2010-9-18 00:11:02的发言:[/b]

像楼主一样,我也写过QQ找茬的辅助程序,QQ找茬游戏有一种简单的防作弊算法,因此通过简单判断两个像素是否相同是不准确的。
就像楼主那样找出很多不重要的不同点。



[/quote]望不吝赐教


页: [1]

编程论坛