【发布时间】:2017-03-11 21:50:22
【问题描述】:
我一直在尝试这段代码,我有一个图像,然后我可以根据我单击并拖动鼠标的时间绘制一个矩形。在 Mouse Down 事件中,我将 x 和 y 坐标标记为矩形的初始角。在鼠标移动时,我从保存的旧 x 和 y 坐标绘制矩形到鼠标所在的新坐标。最后,在 Mouse Up 上,我将矩形绘制为最终的。
这是我正在使用的代码:
import cv2
import numpy as np
drawing = False # True if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix, iy = -1, -1
# mouse callback function
def draw_circle(event, x, y, flags, param):
global ix, iy, drawing, mode, overlay, output, alpha
overlay = img.copy()
output = img.copy()
alpha = 0.5
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix, iy = x, y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
cv2.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), -1)
cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, img)
cv2.imshow('image', img)
else:
cv2.circle(overlay, (x,y),5,(0,0,255),-1)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
if mode == True:
cv2.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), -1)
cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, img)
else:
cv2.circle(overlay, (x, y), 5, (0, 0, 255), -1)
##img = np.zeros((512, 512, 3), np.uint8)
# Get our image
img = cv2.imread("bed_cv.jpg", 1)
#make cv2 windows, set mouse callback
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_circle)
while(1):
cv2.imshow('image', img)
# This is where we get the keyboard input
# Then check if it's "m" (if so, toggle the drawing mode)
k = cv2.waitKey(1) & 0xFF
if k == ord('m'):
mode = not mode
elif k == 27:
break
cv2.destroyAllWindows()
当然这里的问题是,如果我从中心开始,然后拖动到右下角,然后回到左下角,第一个矩形不会被删除。当然,这是因为我实际上是在图像上绘制矩形而不是清除它,所以在鼠标移动事件上创建的每个矩形都会被绘制。
我想要达到的效果类似于你在桌面上绘制一个框,并且你可以在不制作矩形的情况下四处改变方向。
我的问题是,是否可以在视觉上绘制一个矩形但还不能将其写入图像?
【问题讨论】:
-
见here。我通常会保留原始图像的副本、已绘制所有矩形的图像(图层副本)以及绘制我现在正在创建的“部分矩形”的图层副本的副本(工作副本),然后绘制仅工作副本上的矩形。在 mouseUp 上,我将工作副本保存为新图层副本
-
@Miki 感谢您的提示!我设法做到了。我很快就会发布代码。
-
另一种选择是使用一些可逆操作。如果它是一个轮廓,那么您可以使用 XOR 操作来绘制它(尽管对于 OpenCV,您可能需要使用行迭代器来这样做)。对于填充矩形,您可以反转 ROI。当然,这看起来不一样,但这是一种避免保留图像副本的方法。