简体   繁体   English

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

[英]Finding origin pixel of image in OpenCV

In python openCV I am trying to create a GUI where the user has to pick pixels at set y coordinates. 在python openCV中,我试图创建一个GUI,用户必须在该GUI上选择y坐标处的像素。 I can get the openCV pixel location that I want to set the mouse to, but I have no way of tying that to the overall system pixel which is needed for the win32api.SetCursorPos(). 我可以将鼠标设置到openCV像素位置,但是无法将其绑定到win32api.SetCursorPos()所需的整个系统像素。 I have tried moving the image window with cv2.moveWindow('label', x, y) and then offsetting the cursor by y+offset, but this is a very inexact solution. 我尝试过使用cv2.moveWindow('label',x,y)移动图像窗口,然后通过y + offset偏移光标,但这是一个非常不精确的解决方案。 Is there any way to find the current system pixel where the image origin pixel resides? 有什么办法可以找到图像原点像素所在的当前系统像素?

I'm not aware of a way to do this directly with OpenCV (after all, it's meant as convenience for prototyping, rather than a full fledged GUI framework), but since we're on Windows, we can hack it using the WinAPI directly. 我不知道直接使用OpenCV进行编码的方法(毕竟,这是为了方便原型设计,而不是使用完整的GUI框架),但是由于我们使用的是Windows,因此可以直接使用WinAPI对其进行黑客攻击。

NB There's a slight complication -- the callback returns image coordinates, so if scaling is enabled, our precision will be limited, and we have to do some extra work to map the coordinates back to client window coordinates. 注意:这有一点复杂-回调返回图像坐标,因此如果启用缩放,我们的精度将受到限制,并且我们必须做一些额外的工作才能将坐标映射回客户端窗口坐标。


Let's begin by investigating the window hierarchy create by OpenCV for the image display window. 让我们开始研究OpenCV为图像显示窗口创建的窗口层次结构。 We could investigate the source code, but there's a quicker way, using the Spy++ tool from MSVS. 我们可以研究源代码,但是使用MSVS的Spy ++工具有一种更快的方法。

We can write a simple script to show some random data for this: 我们可以编写一个简单的脚本来显示一些随机数据:

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()

When we find this window in Spy++, we can see the following info. 当我们在Spy ++中找到此窗口时,我们可以看到以下信息。

间谍+显示OpenCV HighGUI窗口

There is the top level window, with a caption equal to the window name we specified, of class Main HighGUI class . 有一个类Main HighGUI class的顶级窗口,其标题等于我们指定的窗口名称。 This window contains a single child window, with no caption, and of class HighGUI class . 此窗口包含一个不带标题的子窗口,并且为HighGUI class


The following algorithm comes to mind: 想到以下算法:

  1. Use FindWindow to find the top level window by caption, and get it's window handle. 使用FindWindow按标题查找顶层窗口,并获取它的窗口句柄。

  2. Use GetWindow to get the handle of its child window. 使用GetWindow获取其子窗口的句柄。

  3. Use GetClientRect to get the width and height of the client area (which contains the rendered image). 使用GetClientRect获取工作区(包含渲染的图像)的宽度和高度。

  4. Transform the x and y image-relative coordinates back to client area space. xy图像相对坐标转换回客户区空间。 (We need to know the dimensions of the current image to do this, so we will pass the current image as the user parameter of the callback.) (我们需要知道当前图像的尺寸,以便将当前图像作为回调的用户参数传递。)

  5. Transform the coordinates to screen space using ClientToScreen 使用ClientToScreen将坐标转换为屏幕空间


Sample Script: 示例脚本:

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