Win32API截图后OpenCV模板匹配报错求助
解决OpenCV模板匹配报错:templ is not a numpy array neither a scalar
核心错误原因
报错直接指出templ不是numpy数组或标量——你代码里的target是字符串'box.png',但cv.matchTemplate要求第二个参数必须是加载后的OpenCV图像(numpy数组),而不是文件路径字符串。
分步修复方案
提前加载目标模板图像
在循环开始前用cv.imread()加载模板,避免每次循环重复读取文件:target = cv.imread('box.png') # 检查模板是否加载成功 if target is None: raise FileNotFoundError("无法加载box.png,请检查文件路径是否正确")统一图像通道格式
你的windowcapture函数返回的是RGBA四通道图像(shape=(h,w,4)),而cv.imread默认加载的是BGR三通道图像,两者通道数不匹配会导致模板匹配失败。需要将截图转换为BGR格式:screenshot = windowcapture() # 转换RGBA到BGR screenshot_bgr = cv.cvtColor(screenshot, cv.COLOR_RGBA2BGR)替换过时的numpy API
np.fromstring已被弃用,改用np.frombuffer保证兼容性:# 原代码 # img = np.fromstring(signedIntsArray, dtype='uint8') # 修改为 img = np.frombuffer(signedIntsArray, dtype='uint8')
修改后的完整代码
import cv2 as cv import numpy as np from time import time import win32gui, win32ui, win32con game = 'LOST ARK (64-bit, DX9) v.2.5.3.1' # 提前加载模板图像 target = cv.imread('box.png') if target is None: raise FileNotFoundError("无法找到box.png,请确认文件路径正确") def list_window_names(): def winEnumHandler(hwnd, ctx): if win32gui.IsWindowVisible(hwnd): print(hex(hwnd), win32gui.GetWindowText(hwnd)) win32gui.EnumWindows(winEnumHandler, None) def windowcapture(): hwnd = win32gui.FindWindow(None, game) if hwnd == 0: raise ValueError(f"未找到窗口:{game},请检查窗口标题是否正确") rect = win32gui.GetWindowRect(hwnd) w = rect[2] - rect[0] h = rect[3] - rect[1] wDc = win32gui.GetWindowDC(hwnd) dcObj = win32ui.CreateDCFromHandle(wDc) cDC = dcObj.CreateCompatibleDC() dataBitMap = win32ui.CreateBitmap() dataBitMap.CreateCompatibleBitmap(dcObj, w, h) cDC.SelectObject(dataBitMap) cDC.BitBlt((0, 0), (w, h), dcObj, (0, 0), win32con.SRCCOPY) signedIntsArray = dataBitMap.GetBitmapBits(True) # 替换fromstring为frombuffer img = np.frombuffer(signedIntsArray, dtype='uint8') img.shape = (h, w, 4) dcObj.DeleteDC() cDC.DeleteDC() win32gui.ReleaseDC(hwnd, wDc) win32gui.DeleteObject(dataBitMap.GetHandle()) return img list_window_names() loop_time = time() while True: screenshot = windowcapture() # 转换RGBA到BGR,和模板通道一致 screenshot_bgr = cv.cvtColor(screenshot, cv.COLOR_RGBA2BGR) cv.imshow("computer vision", screenshot_bgr) method = cv.TM_CCORR_NORMED # 推荐使用归一化的匹配方法,结果更稳定 result = cv.matchTemplate(screenshot_bgr, target, method) print('FPS {}'.format(1 / (time() - loop_time))) loop_time = time() if cv.waitKey(1) == ord('q'): cv.destroyAllWindows() break print('Done.')
额外注意事项
- 确认
game变量的窗口标题和实际游戏窗口标题完全一致(可以通过list_window_names()输出的结果核对),如果标题有误,FindWindow会返回0,导致截图失败。 - 如果后续遇到游戏窗口黑屏问题,可能是游戏使用了硬件加速渲染,此时Win32API截图无法捕获画面,可以尝试使用专门针对游戏的截图库。
内容的提问来源于stack exchange,提问作者lycandown
相关产品推荐
相关产品推荐

