【问题标题】:Finding origin pixel of image in OpenCV在 OpenCV 中查找图像的原始像素
【发布时间】:2017-10-19 21:12:49
【问题描述】:

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

【问题讨论】:

  • 也许有点骇人听闻...我知道我们可以使用FindWindow 来获取 OpenCV 创建的顶部窗口的句柄。使用 Spy++,我看到有一个顶级窗口(具有指定的标题,和类“Main HighGUI 类”),其中包含一个绘制图像的子窗口(无标题,类“HighGUI 类”)。所以我们想要那个子窗口的句柄,我想调用ClientToScreen 可以解决问题。 |不确定这对缩放效果如何。

标签: python opencv mouse


【解决方案1】:

我不知道直接使用 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++ 中找到这个窗口时,我们可以看到以下信息。

有一个顶层窗口,其标题与我们指定的窗口名称相同,属于 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多