繁体   English   中英

在OpenCV中查找图像的原点像素

[英]Finding origin pixel of image in OpenCV

在python openCV中,我试图创建一个GUI,用户必须在该GUI上选择y坐标处的像素。 我可以将鼠标设置到openCV像素位置,但是无法将其绑定到win32api.SetCursorPos()所需的整个系统像素。 我尝试过使用cv2.moveWindow('label',x,y)移动图像窗口,然后通过y + offset偏移光标,但这是一个非常不精确的解决方案。 有什么办法可以找到图像原点像素所在的当前系统像素?

我不知道直接使用OpenCV进行编码的方法(毕竟,这是为了方便原型设计,而不是使用完整的GUI框架),但是由于我们使用的是Windows,因此可以直接使用WinAPI对其进行黑客攻击。

注意:这有一点复杂-回调返回图像坐标,因此如果启用缩放,我们的精度将受到限制,并且我们必须做一些额外的工作才能将坐标映射回客户端窗口坐标。


让我们开始研究OpenCV为图像显示窗口创建的窗口层次结构。 我们可以研究源代码,但是使用MSVS的Spy ++工具有一种更快的方法。

我们可以编写一个简单的脚本来显示一些随机数据:

import cv2
import numpy as np

WINDOW_NAME = u'image'

img = np.zeros((512, 512), np.uint8)
cv2.randu(img, 0, 256)

cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL)    
cv2.imshow(WINDOW_NAME, img)
cv2.waitKey()

当我们在Spy ++中找到此窗口时,我们可以看到以下信息。

间谍+显示OpenCV HighGUI窗口

有一个类Main HighGUI class的顶级窗口,其标题等于我们指定的窗口名称。 此窗口包含一个不带标题的子窗口,并且为HighGUI class


想到以下算法:

  1. 使用FindWindow按标题查找顶层窗口,并获取它的窗口句柄。

  2. 使用GetWindow获取其子窗口的句柄。

  3. 使用GetClientRect获取工作区(包含渲染的图像)的宽度和高度。

  4. xy图像相对坐标转换回客户区空间。 (我们需要知道当前图像的尺寸,以便将当前图像作为回调的用户参数传递。)

  5. 使用ClientToScreen将坐标转换为屏幕空间


示例脚本:

import win32gui
from win32con import GW_CHILD
import cv2
import numpy as np

# ============================================================================

def on_mouse(event, x, y, flags, img):
    if event != cv2.EVENT_LBUTTONDOWN:
        return

    window_handle = win32gui.FindWindow(None, WINDOW_NAME)
    child_window_handle = win32gui.GetWindow(window_handle, GW_CHILD)

    (_, _, client_w, client_h) =  win32gui.GetClientRect(child_window_handle)

    image_h, image_w = img.shape[:2]

    real_x = int(round((float(x) / image_w) * client_w))
    real_y = int(round((float(y) / image_h) * client_h))

    print win32gui.ClientToScreen(child_window_handle, (real_x, real_y))

# ----------------------------------------------------------------------------    

def show_with_callback(name, img):
    cv2.namedWindow(name, cv2.WINDOW_NORMAL)    
    cv2.setMouseCallback(name, on_mouse, img)
    cv2.imshow(name, img)
    cv2.waitKey()
    cv2.destroyWindow(name)

# ============================================================================

WINDOW_NAME = u'image'

# Make some test image
img = np.zeros((512, 512), np.uint8)
cv2.randu(img, 0, 256)

show_with_callback(WINDOW_NAME, img)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM