Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在图像opencv上绘制矩形?_Python_Opencv - Fatal编程技术网

Python 在图像opencv上绘制矩形?

Python 在图像opencv上绘制矩形?,python,opencv,Python,Opencv,我已经用python中的opencv库加载了一个图像,现在我想用鼠标画一个矩形,但在画矩形时,矩形应该是可见的,这样画矩形的人就可以把它放在一个位置上,这样感兴趣的对象就完全在矩形中了,但我的代码并没有产生想要的输出 我的代码是 import os import sys import numpy as np import cv2 baseDir = '/home/aman/Downloads/shirt/' filenames = next(os.walk(baseDir))[2] dra

我已经用python中的opencv库加载了一个图像,现在我想用鼠标画一个矩形,但在画矩形时,矩形应该是可见的,这样画矩形的人就可以把它放在一个位置上,这样感兴趣的对象就完全在矩形中了,但我的代码并没有产生想要的输出

我的代码是

import os
import sys
import numpy as np
import cv2

baseDir = '/home/aman/Downloads/shirt/'

filenames = next(os.walk(baseDir))[2]

drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
tx,ty = -1,-1

def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode
    print 'aman'
    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),-1)
            cv2.line(img, (ix,iy),(ix,y), 255, 1, 8, 0)
            cv2.line(img, (ix,iy),(x,iy), 255, 1, 8, 0)

            cv2.line(img, (ix,y),(x,y), 255, 1, 8, 0)
            cv2.line(img, (x,iy),(x,y), 255, 1, 8, 0)
        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),-1)
        cv2.rectangle(img,(ix,y),(x,y),(0,255,0),-1)
        cv2.rectangle(img,(x,iy),(x,y),(0,255,0),-1)
    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()        
`

但产出是这样的


我不想要这种行为,我只想要一个长方形,而不是每个动作。我知道我应该修改鼠标移动事件中的代码,但问题是如何做到这一点,以便当用户移动鼠标时,他能够看到完整的矩形,当他释放按钮时,矩形应该得到修复?

您可以将此过程视为在任何其他渲染API(如OpenGL)中进行渲染:在清洁屏幕,然后在清洁区域绘制

在这种情况下,清理意味着恢复原始图像。利用它意味着增加你的矩形或其他东西

因此,我建议创建一个
draw
方法,只处理这个问题。每当要对渲染目标进行更改时调用它

一个快速片段(不是真正的python,只是伪代码):

如果您希望看到一个真实的示例,下面是一个C++11代码,让您绘制多个三角形,然后将它们的中心作为键盘输入的输出:


我正在解决同一个问题。我找到的解决方案基于:

一切正常,但我对全局变量有点不满意

# initialize the list of points for the rectangle bbox,
# the temporaray endpoint of the drawing rectangle
# the list of all bounding boxes of selected rois
# and boolean indicating wether drawing of mouse
# is performed or not
rect_endpoint_tmp = []
rect_bbox = []
bbox_list_rois = []
drawing = False

def select_rois(img):
"""
Interactive select rectangle ROIs and store list of bboxes.

Parameters
----------
img :
    image 3-dim.

Returns
-------
bbox_list_rois : list of list of int
    List of bboxes of rectangle rois.
"""
# mouse callback function
def draw_rect_roi(event, x, y, flags, param):
        # grab references to the global variables
        global rect_bbox, rect_endpoint_tmp, drawing

        # if the left mouse button was clicked, record the starting
        # (x, y) coordinates and indicate that drawing is being
        # performed. set rect_endpoint_tmp empty list.
        if event == cv2.EVENT_LBUTTONDOWN:
            rect_endpoint_tmp = []
            rect_bbox = [(x, y)]
            drawing = True

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

            # draw a rectangle around the region of interest
            p_1, p_2 = rect_bbox
            cv2.rectangle(img, p_1, p_2, color=(0, 255, 0),thickness=1)
            cv2.imshow('image', img)

            # for bbox find upper left and bottom right points
            p_1x, p_1y = p_1
            p_2x, p_2y = p_2

            lx = min(p_1x, p_2x)
            ty = min(p_1y, p_2y)
            rx = max(p_1x, p_2x)
            by = max(p_1y, p_2y)

            # add bbox to list if both points are different
            if (lx, ty) != (rx, by):
                bbox = [lx, ty, rx, by]
                bbox_list_rois.append(bbox)

        # if mouse is drawing set tmp rectangle endpoint to (x,y)
        elif event == cv2.EVENT_MOUSEMOVE and drawing:
            rect_endpoint_tmp = [(x, y)]


# clone image img and setup the mouse callback function
img_copy = img.copy()
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_rect_roi)

# keep looping until the 'c' key is pressed
while True:
    # display the image and wait for a keypress
    if not drawing:
        cv2.imshow('image', img)
    elif drawing and rect_endpoint_tmp:
        rect_cpy = img.copy()
        start_point = rect_bbox[0]
        end_point_tmp = rect_endpoint_tmp[0]
        cv2.rectangle(rect_cpy, start_point, end_point_tmp,(0,255,0),1)
        cv2.imshow('image', rect_cpy)

    key = cv2.waitKey(1) & 0xFF
    # if the 'c' key is pressed, break from the loop
    if key == ord('c'):
        break
# close all open windows
cv2.destroyAllWindows()

return bbox_list_rois

我能够通过以下代码在黑色背景下实现这一点:-

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

  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)
            q=x
            w=y
            if q!=x|w!=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()            

不过如果你想在图片上加水印,我可以建议你加水印


我一直希望在使用opencv时能够轻松地在图像上拖动矩形。因此,我最终用python编写了这个简单的库,使用opencv来实现这一点。查看实现


如果有人试一试。我很高兴听到一些关于如何改进它或您在其中发现的任何问题的评论。

OpenCv直接在您的图像数据中绘制线条。可以为每个新矩形进行复制和还原,也可以使用适当的Gui工具包。我真的不知道如何在Python中实现这一点(因此给出了注释),但我的想法是通过在每个像素的线条颜色和图像颜色之间执行XOR来绘制每个中间矩形。然后,在绘制下一个矩形之前,再次使用线颜色进行XOR以撤消上一个矩形。在C++中,你会这样做。只有在最后一个矩形上,您才能以最终颜色正常绘制它。
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

  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)
            q=x
            w=y
            if q!=x|w!=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()