Python OpenCV鼠标回调进入无限循环
我有以下代码,应该让用户通过单击图像上的 4 个点来选择 4 边区域(不一定是矩形):
import os
import cv2
FILE_PATH = r'.\img.jpg'
IMAGE_RESIZE_FACTOR = 2
WINDOW_NAME = 'RemoveBG'
img = cv2.imread(FILE_PATH)
print(f'File: "{os.path.abspath(FILE_PATH)}"')
h, w, *_ = img.shape
cv2.imshow(WINDOW_NAME, cv2.resize(img, (w // IMAGE_RESIZE_FACTOR, h // IMAGE_RESIZE_FACTOR)))
print(f'Image size (h x w): {h} x {w}')
def mark_point(event, x, y, flags, param):
global img
global marked_points
if event == cv2.EVENT_LBUTTONDBLCLK:
x *= IMAGE_RESIZE_FACTOR
y *= IMAGE_RESIZE_FACTOR
print(f'({x}, {y})')
img = cv2.circle(img, (x, y), 100, (0, 0, 0), -1)
marked_points += [(x, y)]
marked_points = []
cv2.setMouseCallback(WINDOW_NAME, mark_point)
print(f'Define the 4-sided polygon where the sketch resides:')
for i in range(1, 4+1):
print(f' Please click on point {i}: ', end='')
cv2.waitKey()
cv2.imshow(WINDOW_NAME, cv2.resize(img, (w // IMAGE_RESIZE_FACTOR, h // IMAGE_RESIZE_FACTOR)))
print(marked_points)
cv2.waitKey()
cv2.destroyAllWindows()
我遇到的问题是:
- 此行执行:
print(f'定义草图所在的 4 边多边形:')
- 我们进入循环,
- 使用调试器单步执行此行:
print(f' Please click on point {i}: ', end=' ')
- 当我迈步时什么也没有发生越过第 3 点处的线路。控制台上没有任何文本,什么也没有。
- 我双击图像,回调工作正常,现在步骤 3 中的打印和回调中的打印都会立即执行。
waitKey
似乎会永远运行。就像它进入了自己的 while True: waitKey() 循环一样,因为无论我点击多少次,我都不会进入 for 循环的第二次迭代。我在控制台上的输出如下所示:
Image size (h x w): 2048 x 1532
Define the 4-sided polygon where the sketch resides:
Please click on point 1: (280, 598)
(544, 692)
(794, 902)
(916, 1052)
(1130, 1174)
我试图简单地获取 4 个点的坐标。
我尝试查找 opencv 处理回调的方式是否有任何奇怪的地方,但文档在细节上非常模糊。另外,我尝试从回调中返回 True,因为某些库需要您明确表示该事件在被释放之前已被“消耗”。
我的问题是:
- 这里发生了什么?为什么 waitKey 在 for 循环中没有返回?
- 可以采取什么措施来获得所需的行为?
I have the following code that should let the user select a 4-sided area (not necessarily a rectangle) by clicking on 4 points on an image:
import os
import cv2
FILE_PATH = r'.\img.jpg'
IMAGE_RESIZE_FACTOR = 2
WINDOW_NAME = 'RemoveBG'
img = cv2.imread(FILE_PATH)
print(f'File: "{os.path.abspath(FILE_PATH)}"')
h, w, *_ = img.shape
cv2.imshow(WINDOW_NAME, cv2.resize(img, (w // IMAGE_RESIZE_FACTOR, h // IMAGE_RESIZE_FACTOR)))
print(f'Image size (h x w): {h} x {w}')
def mark_point(event, x, y, flags, param):
global img
global marked_points
if event == cv2.EVENT_LBUTTONDBLCLK:
x *= IMAGE_RESIZE_FACTOR
y *= IMAGE_RESIZE_FACTOR
print(f'({x}, {y})')
img = cv2.circle(img, (x, y), 100, (0, 0, 0), -1)
marked_points += [(x, y)]
marked_points = []
cv2.setMouseCallback(WINDOW_NAME, mark_point)
print(f'Define the 4-sided polygon where the sketch resides:')
for i in range(1, 4+1):
print(f' Please click on point {i}: ', end='')
cv2.waitKey()
cv2.imshow(WINDOW_NAME, cv2.resize(img, (w // IMAGE_RESIZE_FACTOR, h // IMAGE_RESIZE_FACTOR)))
print(marked_points)
cv2.waitKey()
cv2.destroyAllWindows()
The problem I am having is this:
- This line executes:
print(f'Define the 4-sided polygon where the sketch resides:')
- We enter the loop
- I step over this line with the debugger:
print(f' Please click on point {i}: ', end='')
- Nothing happens as I step over the line at point 3. No text on the console, nothing.
- I double click on the image, the callback works correctly, now both the print from step 3 and the print from the callback execute at once.
waitKey
seems to run forever. Like it enters its own loop ofwhile True: waitKey()
, because no matter how many times I click, I do not get to the 2nd iteration of the for loop. My output on the console looks like this:
Image size (h x w): 2048 x 1532
Define the 4-sided polygon where the sketch resides:
Please click on point 1: (280, 598)
(544, 692)
(794, 902)
(916, 1052)
(1130, 1174)
I am trying to simply get the coordinates of 4 points.
I have tried looking up if there is anything weird in how opencv processes callbacks but the documentation is notoriously vague in details. Also I have tried returning True from the callback as some libraries need you to explicitly say that the event is "consumed" before it will be let go.
My questions are:
- What happens here? Why isn't waitKey returning in the for loop?
- What can be done to get the desired behaviour?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论