Python 3.x 在openCV python中绘制矩形

Python 3.x 在openCV python中绘制矩形,python-3.x,opencv,Python 3.x,Opencv,我试图用python中的Opencv使用鼠标作为输入来绘制矩形。我从opencv文档中编写了这段代码。绘制矩形时出现问题,即当您尝试从起点拖动矩形时,会一直绘制到终点。就像我在图片中展示的那样 如何绘制干净的未填充矩形?在那里我可以看到画一个实际的矩形。就像我们在绘画中做的那样 import cv2 import numpy as np drawing = False ix,iy = -1,-1 def draw_rect(event,x,y,flags,param): global ix

我试图用python中的Opencv使用鼠标作为输入来绘制矩形。我从opencv文档中编写了这段代码。绘制矩形时出现问题,即当您尝试从起点拖动矩形时,会一直绘制到终点。就像我在图片中展示的那样

如何绘制干净的未填充矩形?在那里我可以看到画一个实际的矩形。就像我们在绘画中做的那样

import cv2
import numpy as np

drawing = False 
ix,iy = -1,-1

def draw_rect(event,x,y,flags,param):
global ix,iy,drawing,mode

if event == cv2.EVENT_LBUTTONDOWN:
    drawing = True
    ix,iy = x,y

elif event == cv2.EVENT_MOUSEMOVE:
    if drawing == True:
            cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),1)


elif event == cv2.EVENT_LBUTTONUP:
    drawing = False
    cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),1)



img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_rect)

while(1):
cv2.imshow('image',img)
k = cv2.waitKey(1) & 0xFF
if k == 27:
    break

cv2.destroyAllWindows()


谁能告诉我为什么会这样?在
event==cv2.event\u MOUSEMOVE期间移动鼠标时,上面有任何解决方案吗?

同时,您也可以绘制重新绘制的矩形(img,(ix,iy),(x,y),(0255,0),1)

试试下面的代码

import cv2
import numpy as np

drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle.
ix,iy = -1,-1

# mouse callback function
def draw_circle(event,x,y,flags,param):
  global ix,iy,drawing,mode

  if event == cv2.EVENT_LBUTTONDOWN:
      drawing = True
      ix,iy = x,y

  elif event == cv2.EVENT_MOUSEMOVE:
    if drawing == True:
        if mode == True:
            cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),3)
            a=x
            b=y
            if a != x | b != y:
                 cv2.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
        else:
            cv2.circle(img,(x,y),5,(0,0,255),-1)

  elif event == cv2.EVENT_LBUTTONUP:
    drawing = False
    if mode == True:
        cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),2)

    else:
        cv2.circle(img,(x,y),5,(0,0,255),-1)

img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)

while(1):
 cv2.imshow('image',img)
 k = cv2.waitKey(1) & 0xFF
 if k == ord('m'):
    mode = not mode
 elif k == 27:
    break

cv2.destroyAllWindows()   
# import the necessary packages
import cv2
import argparse

# now let's initialize the list of reference point
ref_point = []

def shape_selection(event, x, y, flags, param):
    # grab references to the global variables
    global ref_point, crop

    # if the left mouse button was clicked, record the starting
    # (x, y) coordinates and indicate that cropping is being performed
    if event == cv2.EVENT_LBUTTONDOWN:
        ref_point = [(x, y)]

    # check to see if the left mouse button was released
    elif event == cv2.EVENT_LBUTTONUP:
        # record the ending (x, y) coordinates and indicate that
        # the cropping operation is finished
        ref_point.append((x, y))

        # draw a rectangle around the region of interest
        cv2.rectangle(image, ref_point[0], ref_point[1], (0, 255, 0), 2)
        cv2.imshow("image", image)


# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())

# load the image, clone it, and setup the mouse callback function
image = cv2.imread(args["image"])
clone = image.copy()
cv2.namedWindow("image")
cv2.setMouseCallback("image", shape_selection)


# keep looping until the 'q' key is pressed
while True:
    # display the image and wait for a keypress
    cv2.imshow("image", image)
    key = cv2.waitKey(1) & 0xFF

    # press 'r' to reset the window
    if key == ord("r"):
        image = clone.copy()

    # if the 'c' key is pressed, break from the loop
    elif key == ord("c"):
        break

# close all open windows
cv2.destroyAllWindows() 
希望它能解决你的问题。干杯

预期产出:


更新
上面的代码只适用于黑色背景图像。但我们可以画出任何图像的矩形-

试试下面的代码

import cv2
import numpy as np

drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle.
ix,iy = -1,-1

# mouse callback function
def draw_circle(event,x,y,flags,param):
  global ix,iy,drawing,mode

  if event == cv2.EVENT_LBUTTONDOWN:
      drawing = True
      ix,iy = x,y

  elif event == cv2.EVENT_MOUSEMOVE:
    if drawing == True:
        if mode == True:
            cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),3)
            a=x
            b=y
            if a != x | b != y:
                 cv2.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
        else:
            cv2.circle(img,(x,y),5,(0,0,255),-1)

  elif event == cv2.EVENT_LBUTTONUP:
    drawing = False
    if mode == True:
        cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),2)

    else:
        cv2.circle(img,(x,y),5,(0,0,255),-1)

img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)

while(1):
 cv2.imshow('image',img)
 k = cv2.waitKey(1) & 0xFF
 if k == ord('m'):
    mode = not mode
 elif k == 27:
    break

cv2.destroyAllWindows()   
# import the necessary packages
import cv2
import argparse

# now let's initialize the list of reference point
ref_point = []

def shape_selection(event, x, y, flags, param):
    # grab references to the global variables
    global ref_point, crop

    # if the left mouse button was clicked, record the starting
    # (x, y) coordinates and indicate that cropping is being performed
    if event == cv2.EVENT_LBUTTONDOWN:
        ref_point = [(x, y)]

    # check to see if the left mouse button was released
    elif event == cv2.EVENT_LBUTTONUP:
        # record the ending (x, y) coordinates and indicate that
        # the cropping operation is finished
        ref_point.append((x, y))

        # draw a rectangle around the region of interest
        cv2.rectangle(image, ref_point[0], ref_point[1], (0, 255, 0), 2)
        cv2.imshow("image", image)


# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())

# load the image, clone it, and setup the mouse callback function
image = cv2.imread(args["image"])
clone = image.copy()
cv2.namedWindow("image")
cv2.setMouseCallback("image", shape_selection)


# keep looping until the 'q' key is pressed
while True:
    # display the image and wait for a keypress
    cv2.imshow("image", image)
    key = cv2.waitKey(1) & 0xFF

    # press 'r' to reset the window
    if key == ord("r"):
        image = clone.copy()

    # if the 'c' key is pressed, break from the loop
    elif key == ord("c"):
        break

# close all open windows
cv2.destroyAllWindows() 

将文件另存为
capture_events.py
,为了进行测试,我们选择了位于同一目录下的演示图片。现在,通过以下方式运行代码-

python capture_events.py——image demo.jpg

预期产出:

如果出于某种原因,我们想重新选择图像的任何部分,我们只需按“r”键即可摆脱错误的选择,然后尝试新的选择


希望,这会有更多帮助。选中此项,您可以在此基础上实现更多功能。干杯。

您可以将按下鼠标事件更改为类似的内容

elif event == cv2.EVENT_MOUSEMOVE:
if drawing==True:
    copy = image.copy()
    cv2.rectangle(copy,(ix,iy),(x,y),(0,255,0),1)
    cv2.imshow("image", copy)

脚本将根据当前的x和y创建带有矩形的图像副本,并显示实时效果

我通过使用副本解决了这个问题。现在只需一次imshow()更新就可以了。使用全局变量可能不是最好的

import cv2 as cv


drawing = False
ix, iy = -1, -1


def draw_markers(event, x, y, flags, param):
    global ix, iy, drawing, frame, frame_copy
    if flags == cv.EVENT_FLAG_ALTKEY + cv.EVENT_FLAG_LBUTTON:
        if event == cv.EVENT_LBUTTONDOWN:
            print("Alt + lmouse down")
            drawing = True
            ix, iy = x, y
            frame_copy = frame.copy()
        elif event == cv.EVENT_MOUSEMOVE:
            if drawing:
                frame = cv.rectangle(
                    frame_copy.copy(), (ix, iy), (x, y), (0, 255, 0), 2)
        elif event == cv.EVENT_LBUTTONUP:
            print("Alt + lmouse up")
            drawing = False
            cv.rectangle(frame, (ix, iy), (x, y), (0, 255, 0), 2)

    elif event == cv.EVENT_LBUTTONUP:
        print("Draw crosshair")
        cv.drawMarker(frame, (x, y), (255, 0, 0), 0, 16, 2, 8)


cap = cv.VideoCapture('video.avi')
cap.set(cv.CAP_PROP_POS_FRAMES, 1)
ret, frame = cap.read()
frame_copy = frame.copy()
cv.namedWindow('frame')
cv.setMouseCallback('frame', draw_markers)

while(True):
    cv.imshow('frame', frame)
    if cv.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

在前面答案的基础上,我创建了一个脚本,可以在图像上绘制矩形和任意大小的圆。在按住鼠标左键的同时移动鼠标,矩形会随之更新。分别按下r或t,圆圈变大或变小。按“m”在模式之间切换。按“x”重置图像(删除您绘制的所有内容)。 这是代码,显然它可以被优化更多,我将在这方面的工作

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
x_, y_ = 0,0
r = 15 #circle radius
# mouse callback function
def draw_shape(event,x,y,flags,param):
    print(event)
    global ix,iy,drawing,mode,x_,y_, r

    if event == cv2.EVENT_LBUTTONDOWN:
        print('inside mouse lbutton event....')
        drawing = True
        ix,iy = x,y
        x_,y_ = x,y
    elif event == cv2.EVENT_MOUSEMOVE and drawing:
        copy = img.copy()
        x_,y_ = x,y
        if mode:
            cv2.rectangle(copy,(ix,iy),(x_,y_),(0,255,0),1)
            cv2.imshow("image", copy)
        else:
            cv2.circle(copy,(x,y),r,(0,0,255),1)
            cv2.imshow('image', copy)
    #
    elif event == cv2.EVENT_LBUTTONUP:
        print('inside mouse button up event')
        drawing = False
        if mode:
            cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),1)
        else:
            cv2.circle(img,(x,y),r,(0,0,255),1)


img = np.zeros((512,512,3), np.uint8)
temp_img = np.copy(img)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_shape)
while(1):
    # print('inside while loop...')
    cv2.imshow('image',img)
    if not cv2.EVENT_MOUSEMOVE:
        copy = img.copy()
        # print('x_: , y_ : '.format(x_,y_))
        print(x_)
        if mode == True:
            cv2.rectangle(copy,(ix,iy),(x_,y_),(0,255,0),1)
            cv2.imshow('image',copy)
        else:
            cv2.circle(copy,(x_,y_),r,(0,0,255),1)
            cv2.imshow('image',copy)
    k = cv2.waitKey(1) & 0xFF
    if k == ord('m'): #toggle between circle and rectangle
        mode = not mode
        x_,y_ = -10,-10
        ix,iy = -10,-10
    elif k == ord('r') and not mode: #make circle bigger
        r += 1
    elif k == ord('t') and not mode: #make circle smaller
        if r <=2:
            r = 1
        else:
            r -= 1
    elif k == ord('x'): #resets the image (removes circles and rectangles)
        img = np.copy(temp_img)
        x_,y_ = -10,-10
        ix,iy = -10,-10
    elif k == 27:
        break
cv2.destroyAllWindows()
导入cv2
将numpy作为np导入
绘图=假#如果按下鼠标,则为真
mode=True#如果为True,则绘制矩形。按“m”切换到曲线
ix,iy=-1,-1
x_u,y_u=0,0
r=15#圆半径
#鼠标回调函数
def draw_形状(事件、x、y、标志、参数):
打印(事件)
全局ix,iy,绘图,模式,x_uuu,y_uur
如果event==cv2.event\u LBUTTONDOWN:
打印('鼠标按下事件内部…')
绘图=真
ix,iy=x,y
x_uu,y_uu=x,y
elif event==cv2.event\u鼠标移动和绘图:
copy=img.copy()
x_uu,y_uu=x,y
如果模式:
cv2.矩形(复制,(ix,iy),(x_uu,y_uu),(0255,0),1)
cv2.imshow(“图像”,副本)
其他:
cv2.圆圈(复印件,(x,y),r,(0,0255),1)
cv2.imshow(“图像”,副本)
#
elif event==cv2.event\u LBUTTONUP:
打印('鼠标内键向上事件')
绘图=错误
如果模式:
cv2.矩形(img,(ix,iy),(x,y),(0255,0),1)
其他:
cv2.圆(img,(x,y),r,(0,0255),1)
img=np.zero((512512,3),np.uint8)
临时img=np.副本(img)
cv2.namedWindow(“图像”)
cv2.setMouseCallback(“图像”,绘制形状)
而(一):
#打印('内部while循环…')
cv2.imshow(“图像”,img)
如果不是cv2.EVENT\u MOUSEMOVE:
copy=img.copy()
#打印('x,y:'。格式(x,y))
打印(x)
如果mode==True:
cv2.矩形(复制,(ix,iy),(x_uu,y_uu),(0255,0),1)
cv2.imshow(“图像”,副本)
其他:
cv2.圆圈(复制,(x,y),r,(0,0255),1)
cv2.imshow(“图像”,副本)
k=cv2。等待键(1)和0xFF
如果k==ord('m'):#在圆形和矩形之间切换
模式=非模式
x,y=-10,-10
ix,iy=-10,-10
elif k==ord('r'),非模式:#使圆变大
r+=1
elif k==ord('t'),非模式:#使圆变小

如果你看到。。。移植到python应该不难,因为在
event==cv2.event\u MOUSEMOVE
期间移动鼠标时,您同时也在绘制重新绘制的矩形(img,(ix,iy),(x,y),(0255,0),1)
@JeruLuke完全正确…:有什么解决办法吗。。?谢谢@Niranjankulkarni你没看到答案吗?@iPhoton你能解释一下你的代码发生了什么吗x | b!=y这行代码在做什么???@iPhoton您的代码仅适用于具有黑色背景的图像…不适用于任何图片。“我们怎么能这样做呢?”@Niranjankulkarni嗨,很抱歉回复晚了,这几天身体不适。但是,请检查给出的答案一次,它是更新的。欢迎您查看我的网页,了解更多酷的东西。@iPhoton嘿,谢谢。。我在等待答复。。。是的,那也很好。。我将重新检查代码。非常感谢。