基于opencv实现桌面图标识别

一、必要的库

numy和opencv。直接使用pip安装即可;

二、在指定区域截图

直接贴代码:

from ctypes import windll, byref, c_ubyte
from ctypes.wintypes import RECT, HWND
import numpy as np
import time
from win32com.client import Dispatch
# import mouse as mouse
GetDC = windll.user32.GetDC
CreateCompatibleDC = windll.gdi32.CreateCompatibleDC
GetClientRect = windll.user32.GetClientRect
CreateCompatibleBitmap = windll.gdi32.CreateCompatibleBitmap
SelectObject = windll.gdi32.SelectObject
BitBlt = windll.gdi32.BitBlt
SRCCOPY = 0x00CC0020
GetBitmapBits = windll.gdi32.GetBitmapBits
DeleteObject = windll.gdi32.DeleteObject
ReleaseDC = windll.user32.ReleaseDC

# 防止UI放大导致截图不完整
#windll.user32.SetProcessDPIAware()

def capture(handle: HWND):
    """窗口客户区截图

    Args:
        handle (HWND): 要截图的窗口句柄

    Returns:
        numpy.ndarray: 截图数据
    """
    # 获取窗口客户区的大小
    r = RECT()
    GetClientRect(handle, byref(r))
    width, height = r.right, r.bottom
    print("width,height:", width, height)
    # 开始截图
    dc = GetDC(handle)
    cdc = CreateCompatibleDC(dc)
    # 内存中创建,防止屏幕在截图的时候闪烁,同时,如果知道需要识别的图标的大致范围,则可以
    # 在这个地方将width和height改成对应区域的宽度和高度信息
    bitmap = CreateCompatibleBitmap(dc,  width, height)
    SelectObject(cdc, bitmap)
    # 这里可以设置截图的区域,要和上面的宽度和高度对应,后续的宽度和高度都要对应起来,否则会不匹配
    BitBlt(cdc, 0, 0, width, height, dc, 0, 0, SRCCOPY)
    # 截图是BGRA排列,因此总元素个数需要乘以4
    total_bytes =  width*height*4
    buffer = bytearray(total_bytes)
    byte_array = c_ubyte*total_bytes
    GetBitmapBits(bitmap, total_bytes, byte_array.from_buffer(buffer))
    DeleteObject(bitmap)
    DeleteObject(cdc)
    ReleaseDC(handle, dc)
    # 返回截图数据为numpy.ndarray
    return np.frombuffer(buffer, dtype=np.uint8).reshape( width, height, 4)

if __name__ == "__main__":
    import cv2
    op=Dispatch("op.opsoft")
    handle = windll.user32.FindWindowW(None, "这里是窗口句柄或者名字")
    # 截图时要保证游戏窗口的客户区大小是1334×750
    print(handle)
    image = capture(handle)
    # 转为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
    # 读取图片,并保留Alpha通道,若要排除背景干扰,需要将源对比图背景设置成透明的,即Alpha通道置为0.
    #这里替换成自己的想要抓的图,可以是jpg格式的截图
    template = cv2.imread('23.PNG', cv2.IMREAD_UNCHANGED)
    # 转为灰度图
    template_gray = cv2.cvtColor(template, cv2.COLOR_BGRA2GRAY)
    # 取出Alpha通道
    alpha = template[:,:,3]

    # 模板匹配,将alpha作为mask,TM_CCORR_NORMED方法的计算结果范围为[0, 1],越接近1越匹配 TM_CCOEFF_NORMED
    result = cv2.matchTemplate(gray, template_gray, cv2.TM_CCOEFF_NORMED,mask=alpha)

    # TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
    # TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
    # TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
    # TM_SQDIFF_NORMED 归一化平方差匹配法
    # TM_CCORR_NORMED 归一化相关匹配法
    # TM_CCOEFF_NORMED 归一化相关系数匹配法
    # result = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)

    print(cv2.minMaxLoc(result))
    # 获取结果中最大值和最小值以及他们的坐标
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    # 匹配最大值的坐标,左上角
    top_left = max_loc
    print("左上角坐标值:",top_left[0],top_left[1])
    # 模板的高度和宽度
    h, w = template.shape[:2]
    # 右下角的坐标
    bottom_right = top_left[0] + w, top_left[1] + h
    if max_val>0.8:
        # 在窗口截图中匹配位置画红色方框,在image上画出左上角为top_left,右下角为bottom_right的坐标的矩形
        cv2.rectangle(image, top_left, bottom_right, (0,0,255), 2)
        #大漠插件的鼠标移动,也可以使用win32的鼠标控制
        op.MoveTo(top_left[0]+4,top_left[1]+4)
    cv2.imshow('Match Template', image)
    cv2.waitKey()

然后,依据此可以改成的自动化操作。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蒙蒂锅巴

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

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

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

打赏作者

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

抵扣说明:

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

余额充值