CV_IMAGE_ELEM读取某点的像素

本文详细解释了如何使用OpenCV宏CV_IMAGE_ELEM从灰度和彩色图像中提取像素值,强调了坐标顺序的重要性,并提供了解决访问越界错误的方法。
 

 可以使用opencv定义的宏来提取象素值
假设灰度图像image,存取其i行j列的象素可以这样:CV_IMAGE_ELEM(image, uchar,y, x)
如果是彩色图像就是
CV_IMAGE_ELEM(image, uchar,y, 3*x)
CV_IMAGE_ELEM(image, uchar,y, 3*x+1)
CV_IMAGE_ELEM(image, uchar,y, 3*x+2)

 

CV_IMAGE_ELEM是一个宏,

#define CV_IMAGE_ELEM( image, elemtype, row, col ) \
(((elemtype*)((image)->imageData + (image)->widthStep*(row)))[(col)])

#define CV_MAT_ELEM( mat, elemtype, row, col ) \
(*(elemtype*)CV_MAT_ELEM_PTR_FAST( mat, row, col, sizeof(elemtype)))

呵呵,我一直把它当一个函数用,其实本质也没有什么区别的

但要想正确的得到图像的坐标为(x,y)点的像素值,是应该这样写CV_IMAGE_ELEM(Image, uchar, y, x)

要注意像素点的坐标xy和行列值的顺序是相反的(可以仔细思考为什么)

我刚开始一直写成CV_IMAGE_ELEM(Image, uchar, x, y),结果有时候就造成了访问image越界,从而报错,花了好长时间才捣鼓出来,

不过将IMAGE的数据按照原来的样子复制到mat中可以这么写:
CV_IMAGE_ELEM(pImage, uchar, i, j) = CV_MAT_ELEM(*mat, uchar, i, j)

不用改变顺序

总之,当应用这个宏是如果老报错,就试试换个顺序,或者检查访问的地址是否越界

import os import time import win32api import win32con import win32gui import win32ui import numpy as np import cv2 import pyautogui import tkinter as tk from tkinter import filedialog # 图像识别函数 def getpng(pngname, img): """使用模板匹配识别图像""" temp = cv2.imread(pngname, 0) tw, th = temp.shape[::-1] res = cv2.matchTemplate(img, temp, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) if max_val >= 0.65: return True, max_loc, tw, th else: return False, None, None, None # 图像识别并击函数 def getpngandclick(pngname, img): """识别图像并击""" found, max_loc, tw, th = getpng(pngname, img) if found: top_left = max_loc tagHalfW = int(tw / 2) tagHalfH = int(th / 2) targetx = top_left[0] + tagHalfW targety = top_left[1] + tagHalfH pyautogui.moveTo(targetx, targety) pyautogui.sleep(1) pyautogui.click() return True else: return False class AutoUtil: def __init__(self, hwnd): self.hwnd = hwnd def capture_screen(self): """捕获当前窗口的屏幕截图并保存为BMP文件""" try: left, top, right, bot = win32gui.GetWindowRect(self.hwnd) width = right - left height = bot - top hWndDC = win32gui.GetWindowDC(self.hwnd) mfcDC = win32ui.CreateDCFromHandle(hWndDC) saveDC = mfcDC.CreateCompatibleDC() saveBitMap = win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, width, height) saveDC.SelectObject(saveBitMap) saveDC.BitBlt((0, 0), (width, height), mfcDC, (0, 0), win32con.SRCCOPY) signedIntsArray = saveBitMap.GetBitmapBits(True) im_opencv = np.frombuffer(signedIntsArray, dtype='uint8') im_opencv.shape = (height, width, 4) cv2.cvtColor(im_opencv, cv2.COLOR_BGRA2RGB) cv2.imencode(".bmp", im_opencv)[1].tofile('截图' + str(self.hwnd) + '.bmp') win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(self.hwnd, hWndDC) except Exception as e: print(f'异常: {e}') def click(self, x, y): """模拟鼠标击""" posi = win32api.MAKELONG(int(x), int(y)) win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, posi) win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, posi) def double_click(self, x, y): """模拟鼠标双击""" self.click(x, y) self.click(x, y) def type_keys(self, text): """模拟键盘输入""" for char in text: win32api.SendMessage(self.hwnd, win32con.WM_CHAR, ord(char), 0) time.sleep(0.1) def press_enter(self): """模拟按下回车键""" win32api.SendMessage(self.hwnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0) win32api.SendMessage(self.hwnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0) def right_click(self, x, y): """模拟鼠标右键击""" posi = win32api.MAKELONG(int(x), int(y)) win32api.SendMessage(self.hwnd, win32con.WM_RBUTTONDOWN, win32con.MK_RBUTTON, posi) win32api.SendMessage(self.hwnd, win32con.WM_RBUTTONUP, win32con.MK_RBUTTON, posi) def main(): # 创建一个Tkinter主窗口实例 root = tk.Tk() root.withdraw() # 隐藏主窗口 # 加载大图和小图文件夹 large_image_folder = filedialog.askdirectory(title="选择大图文件夹") small_image_folder = filedialog.askdirectory(title="选择小图文件夹") if not large_image_folder or not small_image_folder: print("未选择大图或小图文件夹") return # 第一步:打开SAP应用 hwnd = win32gui.FindWindow(None, "SAP Logon 770") if not hwnd: print("未找到SAP Logon 770窗口") return auto_util = AutoUtil(hwnd) # 第二步:双击第一个位置“00.ASM_生产” auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "00.ASM_生产.png") if getpngandclick(template_path, screenshot): time.sleep(3) # 第三步:登录 hwnd = win32gui.FindWindow(None, "SAP") if not hwnd: print("未找到SAP窗口") return auto_util = AutoUtil(hwnd) auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "用户.png") if getpng(template_path, screenshot)[0]: posi = getpng(template_path, screenshot)[1] tw, th = getpng(template_path, screenshot)[2], getpng(template_path, screenshot)[3] targetx = posi[0] + int(tw / 2) targety = posi[1] + int(th / 2) pyautogui.moveTo(targetx, targety) pyautogui.sleep(1) pyautogui.click() auto_util.type_keys("60005847") time.sleep(3) template_path = os.path.join(small_image_folder, "口令.png") if getpng(template_path, screenshot)[0]: posi = getpng(template_path, screenshot)[1] tw, th = getpng(template_path, screenshot)[2], getpng(template_path, screenshot)[3] targetx = posi[0] + int(tw / 2) targety = posi[1] + int(th / 2) pyautogui.moveTo(targetx, targety) pyautogui.sleep(1) pyautogui.click() auto_util.type_keys("Zc1472580.") time.sleep(3) auto_util.press_enter() time.sleep(5) # 第四步:进入“ZWMR119 - 库存总览表” hwnd = win32gui.FindWindow(None, "SAP 轻松访问 - 用户菜单 张驰") if not hwnd: print("未找到SAP 轻松访问 - 用户菜单 张驰窗口") return auto_util = AutoUtil(hwnd) auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "ZWMR119 - 库存总览表.png") if getpngandclick(template_path, screenshot): time.sleep(2) # 第五步:输入工厂和存储位置 hwnd = win32gui.FindWindow(None, "库存总览报表") if not hwnd: print("未找到库存总览报表窗口") return auto_util = AutoUtil(hwnd) auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "工厂.png") if getpng(template_path, screenshot)[0]: posi = getpng(template_path, screenshot)[1] tw, th = getpng(template_path, screenshot)[2], getpng(template_path, screenshot)[3] targetx = posi[0] + int(tw / 2) targety = posi[1] + int(th / 2) pyautogui.moveTo(targetx, targety) pyautogui.sleep(1) pyautogui.click() auto_util.type_keys("2482") time.sleep(3) template_path = os.path.join(small_image_folder, "存储位置.png") if getpng(template_path, screenshot)[0]: posi = getpng(template_path, screenshot)[1] tw, th = getpng(template_path, screenshot)[2], getpng(template_path, screenshot)[3] targetx = posi[0] + int(tw / 2) targety = posi[1] + int(th / 2) pyautogui.moveTo(targetx, targety) pyautogui.sleep(1) pyautogui.click() auto_util.type_keys("IH02") time.sleep(3) # 第六步:击图标 hwnd = win32gui.FindWindow(None, "库存总览报表") if not hwnd: print("未找到库存总览报表窗口") return auto_util = AutoUtil(hwnd) auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "图标.png") if getpngandclick(template_path, screenshot): time.sleep(2) # 第七步:选择“电子表格” hwnd = win32gui.FindWindow(None, "库存总览报表") if not hwnd: print("未找到库存总览报表窗口") return auto_util = AutoUtil(hwnd) auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "空白处.png") if getpng(template_path, screenshot)[0]: posi = getpng(template_path, screenshot)[1] tw, th = getpng(template_path, screenshot)[2], getpng(template_path, screenshot)[3] targetx = posi[0] + int(tw / 2) targety = posi[1] + int(th / 2) pyautogui.moveTo(targetx, targety) pyautogui.sleep(1) pyautogui.rightClick() time.sleep(2) template_path = os.path.join(small_image_folder, "电子表格.png") if getpngandclick(template_path, screenshot): time.sleep(2) hwnd = win32gui.FindWindow(None, "选择电子表格") if not hwnd: print("未找到选择电子表格窗口") return auto_util = AutoUtil(hwnd) auto_util.capture_screen() screenshot = cv2.imread('截图' + str(hwnd) + '.bmp', 0) template_path = os.path.join(small_image_folder, "√按钮.png") if getpngandclick(template_path, screenshot): time.sleep(2) template_path = os.path.join(small_image_folder, "E路径.png") if getpngandclick(template_path, screenshot): time.sleep(2) template_path = os.path.join(small_image_folder, "保存按钮.png") if getpngandclick(template_path, screenshot): time.sleep(2) print("所有操作步骤完成") if __name__ == "__main__": main()
最新发布
06-04
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值