取得台球游戏的图像

这里为了在窗口被遮挡的时候也能够取得正确图像,我们不能采用屏幕图像传输的方法,而.NET仅提供了一个快捷方法传输屏幕图像,这个方法不适合我们。最终还是决定使用传统的WIN32 API来实现这个功能,涉及到的API和使用方法都是很久以前大家就非常熟悉的,只是把它们用在.NET中时需要更改一些内容。

其API声明如下:


Public Class GDI32
    Public Const SRCCOPY As Integer = 13369376
    <DllImport("gdi32.dll")> _
    Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, _
    ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
    End Function
    <DllImport("gdi32.dll")> _
    Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
    End Function
    <DllImport("gdi32.dll")> _
    Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr
    End Function
    <DllImport("gdi32.dll")> _
    Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
    End Function
    <DllImport("gdi32.dll")> _
    Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
    End Function
    <DllImport("gdi32.dll")> _
    Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
    End Function
End Class

Public Class User32
    <StructLayout(LayoutKind.Sequential)> Public Structure RECT
        Public left As Integer
        Public top As Integer
        Public right As Integer
        Public bottom As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> Public Structure POINT
        Public X As Integer, Y As Integer
    End Structure
    <DllImport("user32.dll")> Public Shared Function GetDesktopWindow() As IntPtr
    End Function
    <DllImport("user32.dll")> Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll")> Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll")> Public Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef rect As RECT) As IntPtr
    End Function
    <DllImport("user32.dll")> Public Shared Function WindowFromPoint(ByVal pt As POINT) As IntPtr
    End Function
End Class

接下来我们实现一个方法,这个方法只需要传入一个Handle,返回值为一个Image对象,这个返回值可以直接转化为BitMap对象供我们分析图像使用。

一下在同一个文件中,该文件开头需要导入名空间:

Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging


Public Class ScreenCapture
    ''' <summary>
    ''' 取得窗口图像
    ''' </summary>
    ''' <param name="handle">句柄</param>
    ''' <returns>图像</returns>
    ''' <remarks></remarks>
    Public Shared Function CaptureWindow(ByVal handle As IntPtr) As Image
        Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
        Dim windowRect As New User32.RECT()
        User32.GetWindowRect(handle, windowRect)
        Dim width As Integer = windowRect.right - windowRect.left
        Dim height As Integer = windowRect.bottom - windowRect.top
        Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
        Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
        Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
        GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY)
        GDI32.SelectObject(hdcDest, hOld)
        GDI32.DeleteDC(hdcDest)
        User32.ReleaseDC(handle, hdcSrc)
        Dim img As Image = Image.FromHbitmap(hBitmap)
        GDI32.DeleteObject(hBitmap)
        Return img
    End Function

End Class

接下来只需要取得台球窗口句柄就可以了,这里还是使用传统的API来实现,使用SPY++即可得到这个窗口的类名信息,我们取最小的子窗口。这个方法同样需要一个传入参数,我们的瞄准器采取事件驱动模式,所以传入参数定位为鼠标所在坐标,那么这个函数实际上就是已知鼠标坐标,返回窗口Handle,但在SPY++中观察,发现有一个窗口和本窗口很相似,所以为了区分,我们遍历其所有父及父的父(也就是他爷爷,最后到了他爷爷的爹或者他爹的爷爷)。。。。。。。

Public Class GameFrame
    'api
    Private Declare Function WindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Integer, ByVal yPoint As Integer) As Integer
    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer
    Private Declare Function GetParent Lib "user32" Alias "GetParent" (ByVal hwnd As IntPtr) As IntPtr
 Private Shared _hwndback As IntPtr '上次取得的台面句柄


    Public Shared Function GetBitMap(ByVal point As Point) As Bitmap
        Dim hwnd As IntPtr = WindowFromPoint(point.X, point.Y)  '鼠标所在窗口
        If hwnd <> _hwndback Then
            Dim Length As Integer = 100
            Dim ClassName As String = Space(100)
            GetClassName(hwnd, ClassName, Length)   '窗口类名
            ClassName = ClassName.Replace(Chr(0), "").Trim
            If ClassName = Setting.CName Then
                Dim phwnd As IntPtr
                If GetpClassname(hwnd, phwnd) = Setting.pCName Then
                    Dim pphwnd As IntPtr
                    If GetpClassname(phwnd, pphwnd) = Setting.ppCName Then
                        Dim ppphwnd As IntPtr
                        If GetpClassname(pphwnd, ppphwnd) = Setting.pppCName Then
                            _hwndback = hwnd    '保存刚取得的句柄
                            Line.Graphics = Graphics.FromHwnd(hwnd)  '【创建画布】
                            Return ScreenCapture.CaptureWindow(hwnd)  '【图像】
                        End If
                    End If
                End If
            End If
        Else
            Line.Graphics = Graphics.FromHwnd(hwnd) '【创建画布】
            Return ScreenCapture.CaptureWindow(hwnd)  '【图像】
        End If
        Return Nothing
    End Function
    '获取父窗口类名
    Private Shared Function GetpClassname(ByVal hwnd As IntPtr, ByRef phwnd As IntPtr) As String
        phwnd = GetParent(hwnd)
        Dim pClassName As String = Space(100)
        GetClassName(phwnd, pClassName, 100)
        pClassName = pClassName.Replace(Chr(0), "").Trim
        Return pClassName
    End Function

End Class

这里的类名放在了Setting类当中,其具体值分别为:

Public Class Setting
    Public Shared CName As String = "AfxWnd42"
    Public Shared pCName As String = "#32770"
    Public Shared ppCName As String = "AfxMDIFrame42"
    Public Shared pppCName As String = "Afx:400000:0"
End Class

 

好了,可以测试了,截取一个台球图像到程序吧!

在窗体上绘制一个PICTUREBOX,命名为PIC,添加一个TIMER控件,修改其为有效。

在TICK事件中添加以下代码:

GameFrame.GetBitMap(500,400)

然后打开联众台球。。。。美式或斯诺克都可以。如果取不到图像,可以调节500,400这个数值。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 起源:OpenCV于1999年由英特尔公司发起,旨在促进计算机视觉技术的普及和商业化应用。该项目旨在创建一个易于使用、高效且跨平台的库,为开发者提供实现计算机视觉算法所需的基础工具。 社区与支持:随着时间的推移,OpenCV吸引了全球众多开发者和研究人员的参与,形成了活跃的社区。目前,OpenCV由非盈利组织OpenCV.org维护,并得到了全球开发者、研究机构以及企业的持续贡献和支持。 主要特点 跨平台:OpenCV支持多种操作系统,包括但不限于Windows、Linux、macOS、Android和iOS,确保代码能够在不同平台上无缝运行。 丰富的功能:库中包含了数千个优化过的函数,涵盖了计算机视觉领域的诸多方面,如图像处理(滤波、形态学操作、色彩空间转换等)、特征检测与描述(如SIFT、SURF、ORB等)、物体识别与检测(如Haar级联分类器、HOG、DNN等)、视频分析、相机校正、立体视觉、机器学习(SVM、KNN、决策树等)、深度学习(基于TensorFlow、PyTorch后端的模型加载与部署)等。 高效性能:OpenCV代码经过高度优化,能够利用多核CPU、GPU以及特定硬件加速(如Intel IPP、OpenCL等),实现高速图像处理和实时计算机视觉应用。 多语言支持:尽管OpenCV主要使用C++编写,但它提供了丰富的API绑定,支持包括C、Python、Java、MATLAB、JavaScript等多种编程语言,方便不同领域的开发者使用。 开源与免费:OpenCV遵循BSD开源许可证发布,用户可以免费下载、使用、修改和分发库及其源代码,无需担心版权问题。 架构与核心模块 OpenCV的架构围绕核心模块构建,这些模块提供了不同层次的功能: Core:包含基本的数据结构(如cv::Mat用于图像存储和操作)、基本的图像和矩阵操作、数学函数、文件I/O等底层功能。 ImgProc:提供图像预处理、滤波、几何变换、形态学操作、直方图计算、轮廓发现与分析等图像处理功能。 HighGui:提供图形用户界面(GUI)支持,如图像和视频的显示、用户交互(如鼠标事件处理)以及简单的窗口管理。 VideoIO:负责视频的读写操作,支持多种视频格式和捕获设备。 Objdetect:包含预训练的对象检测模型(如Haar级联分类器用于人脸检测)。 Features2D:提供特征点检测(如SIFT、ORB)与描述符计算、特征匹配与对应关系估计等功能。 Calib3d:用于相机标定、立体视觉、多视图几何等问题。 ML:包含传统机器学习算法,如支持向量机(SVM)、K近邻(KNN)、决策树等。 DNN:深度神经网络模块,支持导入和运行预训练的深度学习模型,如卷积神经网络(CNN)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清晨曦月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值