大家来找茬图片对比问题 容错算法怎么写才合适?
自己刚学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]]
[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]
sqrt(absR*absR+absG*absG+absB*absB)>100 这个是因为三基色的原理吧
根据图像学原理,我感觉两个图像相减后作均值滤波,然后设置一个阀值应该能找出两者的不同点 [quote][b]以下是引用[u]vfdff[/u]在2010-9-5 03:56:07的发言:[/b]
根据图像学原理,我感觉两个图像相减后作均值滤波,然后设置一个阀值应该能找出两者的不同点[/quote]额...听上去好复杂啊 昨天看了一本数字图像处理的书 感觉跟看高数书是的....
不需要很复杂,给个提示,,“位操作” [quote][b]以下是引用[u]迷失的木桶[/u]在2010-9-5 18:40:29的发言:[/b]
不需要很复杂,给个提示,,“位操作”[/quote]希望这位前辈能多多指点一下 1001000
0111110
--------
1110110
看出上面是什么位操作了吗?
发挥你的想象。 程序算法蛮好的
简单明了
我试验了下
找的很正确[em01]
[[i] 本帖最后由 黑白世界 于 2010-9-14 21:41 编辑 [/i]] [quote][b]以下是引用[u]黑白世界[/u]在2010-9-14 08:37:43的发言:[/b]
程序算法蛮好的
简单明了
我试验了下
找的很正确[em01]
[/quote]楼上说的是我写的算法吗?
我自己用别的找茬游戏试验了一次 的确找得很准 不同的地方能标示得很精确 但是在QQ上的大家来找茬上不是很精准 颜色快的边缘也会被标示出来
像楼主一样,我也写过QQ找茬的辅助程序,QQ找茬游戏有一种简单的防作弊算法,因此通过简单判断两个像素是否相同是不准确的。
就像楼主那样找出很多不重要的不同点。
[quote][b]以下是引用[u]迷失的木桶[/u]在2010-9-18 00:11:02的发言:[/b]
像楼主一样,我也写过QQ找茬的辅助程序,QQ找茬游戏有一种简单的防作弊算法,因此通过简单判断两个像素是否相同是不准确的。
就像楼主那样找出很多不重要的不同点。
[/quote]你有什么好办法 说来听听
谢谢 [quote][b]以下是引用[u]迷失的木桶[/u]在2010-9-18 00:11:02的发言:[/b]
像楼主一样,我也写过QQ找茬的辅助程序,QQ找茬游戏有一种简单的防作弊算法,因此通过简单判断两个像素是否相同是不准确的。
就像楼主那样找出很多不重要的不同点。
[/quote]望不吝赐教
页:
[1]