python win32  opencv 后台找图 后台模拟鼠标点击

使用之前创建的yolo环境,多安装一个pywin32

进入虚拟环境安装pywin32,如果在此电脑安装过pywin32,他会直接使用缓存安装,很烦人,添加–no-cache-dir命令,会重新下载安装。

pip --no-cache-dir install pywin32

将D:\Anaconda3\envs\yolo\Lib\site-packages\pywin32_system32 添加到系统环境变量,yolo是虚拟环境目录。

测试一下,关了命令行窗口,重新打开进入,输入python。输入 import win32api或 import win32gui试一下,不报错就安装成功。

win32+vc2 后台找图,后台模拟鼠标点击代码,大部分代码是网上得来,自己稍做修改。基本都有备注。

import cv2
import numpy
import win32gui, win32con, win32api,win32ui
import os
import random
#获取后台窗口的句柄,注意后台窗口不能最小化.窗口的类名可以用SPY++工具获取,远程桌面子窗口很多,所以拿这个示例,并不是所有的程序都有很多子窗口,我们只要找到那个可操作子窗口即可。具体要自己用SPY++看看
hWnd = win32gui.FindWindow("TscShellContainerClass",None)
print(hWnd)
#可操作窗口一般不是主窗口,一般是子窗口,子窗口必须使用FindWindowEx()函数来进行搜索
hWnd= win32gui.FindWindowEx(hWnd, 0, 'TscShellAxHostClass', None) #在窗口句柄为hwnd的窗口中,寻找子窗口,同样是在spy++工具中看到的窗口信息。TscShellAxHostClass是窗口类名
print(hWnd)
hWnd= win32gui.FindWindowEx(hWnd, 0, 0, None) #父窗口下只有一个子窗口的情况,标题和类名不设置是可以的。因为这个句柄是变化随机值的,并且是唯一子窗口,所以设置0
print(hWnd)
hWnd= win32gui.FindWindowEx(hWnd, 0, 'UIMainClass', None)
print(hWnd)
hWnd= win32gui.FindWindowEx(hWnd, 0, 'UIContainerClass', None)
print(hWnd)
hWnd= win32gui.FindWindowEx(hWnd, 0, 'IHWindowClass', None) #最后,找到可操作的窗口
print(hWnd)
#获取句柄窗口的大小信息
left, top, right, bot = win32gui.GetWindowRect(hWnd)
width = right - left
height = bot - top
#返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框
hWndDC = win32gui.GetWindowDC(hWnd)
#创建设备描述表
mfcDC = win32ui.CreateDCFromHandle(hWndDC)
#创建内存设备描述表
saveDC = mfcDC.CreateCompatibleDC()
#创建位图对象准备保存图片
saveBitMap = win32ui.CreateBitmap()
#为bitmap开辟存储空间
saveBitMap.CreateCompatibleBitmap(mfcDC,width,height)
#将截图保存到saveBitMap中
saveDC.SelectObject(saveBitMap)
#保存bitmap到内存设备描述表,截取从左上角(0,0)长宽为(w,h)的图片
saveDC.BitBlt((0,0), (width,height), mfcDC, (0, 0), win32con.SRCCOPY)
#保存图像
##方法一:windows api保存
#saveBitMap.SaveBitmapFile(saveDC,"img_Winapi.bmp")

#第二种方法,CV2+numpy存图,选择CV2存图原因是CV2对图片有较好的处理功能,比如有些图片有亮度等变化的,可以用CV2处理成灰度或调整色阶等后对比查找。
signedIntsArray = saveBitMap.GetBitmapBits(True) #获取位图信息,
im_opencv = numpy.frombuffer(signedIntsArray, dtype = 'uint8')
im_opencv.shape = (height, width, 4)
cv2.cvtColor(im_opencv, cv2.COLOR_BGRA2RGB)
cv2.imwrite("im_opencv.jpg",im_opencv,[int(cv2.IMWRITE_JPEG_QUALITY), 100]) #保存,这里图片需存到本地,稍影响速度,在寻找直接在内存中处理对比图片的方法,有知道请告知。

#内存释放
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hWnd,hWndDC)

#从截图中查找图片坐标
def find_picd(template: str, threshold: float):
    threshold = 1-threshold
    try:
        scr = cv2.imread(template)
        tp = cv2.imread("im_opencv.jpg")
        result = cv2.matchTemplate(scr, tp, cv2.TM_SQDIFF_NORMED)
    except cv2.error:
        print('文件错误:', template, "im_opencv.jpg")
        try:
            scr = cv2.imread(template)
            tp = cv2.imread("im_opencv.jpg")
            result = cv2.matchTemplate(scr, tp, cv2.TM_SQDIFF_NORMED)
        except cv2.error:
            return False, None
    h, w = scr.shape[:2]
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    if min_val > threshold:
        os.remove("im_opencv.jpg")
        return False, None
    else:
        coordinate=(min_loc[0]+w/2,min_loc[1]+h/2,min_loc[0],min_loc[1],min_loc[0]+w,min_loc[1]+h)
        print(template, min_val, min_loc)
        print(min_loc[0],min_loc[1])
        os.remove("im_opencv.jpg")
        return True, coordinate
a = find_picd("123.jpg", 0.9)
if  a[0] == True:
    print(a)
    click_x = int(a[1][0])  # 点击点的X座标
    click_y = int(a[1][1]) # 点击点的Y座标
    print(click_x,click_y)  #检查点击点的座标
    random_deltax = (random.random() - 0.5) * 15  # 在点击点的附近,x座标上产生一个[-7.5,7.5]区间的均匀分布的随机波动
    random_deltay = (random.random() - 0.5) * 15  # 在点击点的附近,y座标上产生一个[-7.5,7.5]区间的均匀分布的随机波动
    tmp = win32api.MAKELONG(click_x+int(random_deltax), click_y+int(random_deltay))  # 将座标转换成SendMessage()函数需要的一维数据的座标
    print(tmp)
    win32gui.SendMessage(hWnd, win32con.WM_ACTIVATE, win32con.WA_ACTIVE, 0)
    win32gui.SendMessage(hWnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, tmp)  # 鼠标左键在tmp位置按下
    win32gui.SendMessage(hWnd, win32con.WM_LBUTTONUP, 0000, tmp)  # 鼠标左键在tmp位置弹起
    # (弹起时,鼠标左键的代码是0000,有些电脑可能是win32con.MK_LBUTTON,具体情况需要通过手动在界面上点击鼠标左键,看spy++中的显示)
else:
    print("没找到")
1

评论0

显示验证码