打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
学习API—最小白的注解(七)—找图的原理剖析
学习API—最小白的注解(七)—找图的原理剖析
发布: 2013-3-08 14:57 | 作者: 11841830795454 | 来源: 按键精灵资源站
[i=s] 本帖最后由 11841830795454 于 2013-3-10 16:15 编辑

找图——无非是一幅图和另一幅图的比较,找到一幅图在另一幅图中的方位
关键的地方,就是数据的提取
上一章我们认识了基本的设备场景函数,之后还有位图函数,可以分析位图,进而进行找图
下面的例子是提取位图的RGB数据进行比较(VB代码):肯定看不懂的,因为有没讲过的函数,这里只是举个例子,说明下找图的原理,其实是很简单的,如果用按键或大漠被检测,可以试试VB

CODE:

Option Explicit
Dim mousestep As POINTAPI
Dim moubegin As POINTAPI '用于储存鼠标坐标点


'====================================================
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
'将来自一幅位图的二进制位复制到一幅与设备无关的位图里

Private Declare Function SetDIBits Lib "gdi32" (ByVal HDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
'将来自与设备无关位图的二进制位复制到一幅与设备有关的位图里

Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
'鼠标消息

Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
'获取指定窗口的设备场景

Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long '获取图片数据
'将一幅位图从一个设备场景复制到另一个。源和目标DC相互间必须兼容
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal HDC As Long) As Long
'释放DC

Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal HDC As Long) As Long
'创建一个与特定设备场景一致的内存设备场景

Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal HDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
'创建一幅与设备有关位图,它与指定的设备场景兼容,返回位图句柄

Private Declare Function DeleteDC Lib "gdi32" (ByVal HDC As Long) As Long
'删除专用设备场景或信息场景,释放所有相关窗口资源。不要将它用于GetDC函数取回的设备场景

Private Declare Function SelectObject Lib "gdi32" (ByVal HDC As Long, ByVal hObject As Long) As Long
'把一个对象选入设备环境中,可能是图形、区域、刷子、字体或画笔等

Private Const SRCCOPY = &HCC0020 ' (DWORD) dest = source
'
Dim intX As Long
Dim intY As Long

'颜色表
Private Type RGBQUAD
    rgbBlue As Byte
    rgbGreen As Byte
    rgbRed As Byte
    rgbAlpha As Byte   '透明通道
End Type

Private Type BITMAPINFOHEADER
    biSize As Long          '位图大小
    biWidth As Long
    biHeight As Long
    biPlanes As Integer
    biBitCount As Integer   '信息头长度
    biCompression As Long   '压缩方式
    biSizeImage As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As Long
    biClrImportant As Long
End Type

'============================================
Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type
Private Type POINTAPI
        X As Long
        Y As Long
End Type

Private Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
'设置鼠标的位置

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
'得到鼠标位置



Private Type BITMAPINFO
    bmiHeader As BITMAPINFOHEADER
    bmiColors As RGBQUAD
End Type

'图片文件头
Dim BI As BITMAPINFO
Dim BI1 As BITMAPINFO
Dim PP As New Form1 '创建一个新的窗体对象实例


'在图片1中查找图片2
Private Function FindPic(Left As Long, Top As Long, Right As Long, Bottom As Long, fileurl As String)
Dim P2 As Picture, P2W, P2H, P2Handle
Set P2 = LoadPicture(fileurl) '加载图片2
P2W = P2.Width '图片2宽度
P2H = P2.Height '图片2高度
P2Handle = P2.Handle '图片2句柄
Dim W As Long, H As Long, I As Long, J As Long
Dim W2 As Long, H2 As Long, I2 As Long, J2 As Long
Dim zPic() As Byte, fPic() As Byte
Dim R As Byte, G As Byte, B As Byte
'获得图片2数据
W2 = ScaleX(P2W, vbHimetric, 3) '将高度和宽度转变为像素单位
H2 = ScaleY(P2H, 8, 3)
With BI.bmiHeader
    .biSize = Len(BI.bmiHeader)
    .biWidth = W2
    .biHeight = -H2
    .biBitCount = 32
    .biPlanes = 1
End With
ReDim zPic(3, W2 - 1, H2 - 1) '字节数组
I = GetDIBits(HDC, P2Handle, 0, H2, zPic(0, 0, 0), BI, 0) '得到RGB数据,从0到H2扫描数据存到zPic(0, 0, 0)指向的数组里

Set P2 = Nothing '释放图片2对象
'Debug.Print I
'如果在这里处理一下,图像大的话,可能会快一点。



' 获得图片1数据
W = Right '图片1的宽度
H = Bottom '图片1的高度

With BI1.bmiHeader
    .biSize = Len(BI1.bmiHeader)
    .biWidth = W
    .biHeight = -H
    .biBitCount = 32
    .biPlanes = 1
End With

        For J2 = 0 To H2 - 2
            For I2 = 0 To W2 - 2
                PP.PSet (I2, J2), RGB(zPic(2, I2, J2), zPic(1, I2, J2), zPic(0, I2, J2)) '从 zPic中提取图片2的RGB值放到PP中
            Next I2
        Next J2
        PP.Refresh '强制刷新窗体
        
ReDim fPic(3, W - 1, H - 1) '与zPic一样大小

     Dim hBMPhDC
     Dim hDCmem As Long
     Dim Pic1Handle As Long
     Dim hBmpPrev As Long
     hBMPhDC = GetDC(0) '得到屏幕的设备场景
     hDCmem = CreateCompatibleDC(hBMPhDC) '在内存中重新创建一个与屏幕设备场景一样的设备场景内存块
     Pic1Handle = CreateCompatibleBitmap(hBMPhDC, Right, Bottom) '创建与屏幕相关的位图
     hBmpPrev = SelectObject(hDCmem, Pic1Handle) '将这个创建的位图选入新创建的内存设备场景中
     
     '上面的代码是在内存中创建一个设备场景框架,并放入一个空白位图
     
     BitBlt hDCmem, 0, 0, Right, Bottom, hBMPhDC, Left, Top, SRCCOPY '把屏幕的设备场景信息复制到准备好的框架上,空白位图也会被填充入数据
     
     DeleteDC hDCmem '删除新创建的设备场景

I = GetDIBits(hBMPhDC, Pic1Handle, 0, H, fPic(0, 0, 0), BI1, 0) '得到屏幕位图的数据存到fPic中

ReleaseDC 0, hBMPhDC '释放屏幕的设备场景(由调用GetDC或GetWindowDC函数获取的指定设备场景),对其他设备场景无效,但不会造成破坏



'所有数据已经存到了 fPic和 zPic 数组中,接下来就是分析查找

For J = 0 To H - H2 - 1
VBA.DoEvents
    For I = 0 To W - W2 - 1
        
        For J2 = 0 To H2 - 2 '循环判断小图片
            For I2 = 0 To W2 - 2
               
                If fPic(2, I + I2, J + J2) <> zPic(2, I2, J2) Then GoTo ExitLine: 'R
                If fPic(1, I + I2, J + J2) <> zPic(1, I2, J2) Then GoTo ExitLine: 'G
                If fPic(0, I + I2, J + J2) <> zPic(0, I2, J2) Then GoTo ExitLine: 'B

            Next I2
        Next J2

        'Debug.Print "发现:", I, J
        intX = I
        intY = J
     
ExitLine:
    Next I
Next J

End Function
'执行完FindPic函数后,坐标会存到Intx和Inty中
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
VB实用代码,收藏!!
Excel窗体API应用技巧
如何屏蔽掉窗体中的关闭按钮X?
VB 遍历窗口所有子窗体句柄
教大家获取程序的所有模块及模块基址(附代码)
VBA 一个能够获取图像大小(如800*600)的api函数
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服