python使用opencv鼠标动态画矩形框
作者:互联网
cv2.rectangle()函数说明
其中四个参数必选:
- img:底图,uint8类型的ndarray
- pt1:矩形框的一个顶点坐标,是一个包含两个数字的tuple(必需是tuple),表示(x, y)
- pt2:pt1的对角线顶点坐标,类型同pt1
- color:颜色,是一个包含三个数字的tuple或list,表示(b, g, r);如果图片是灰度图的话,color也可以是一个数字
其他参数说明如下:
- thickness:线宽,默认值是1,数值越大表示线宽越宽;如果取值为负数或者cv2.FILLED,那么将画一个填充了的矩形
- lineType:可以取的值有cv2.LINE_4,cv2.LINE_8,cv2.LINE_AA。其中cv2.LINE_AA的AA表示抗锯齿,线会更平滑。
下面是一个非交互式的程序示例
# -*- coding: utf-8 -*- import cv2 import numpy as np if __name__ == '__main__': image = np.zeros((256, 256, 3), np.uint8) color = (0, 255, 0) cv2.rectangle(image, (20, 20), (60, 60), (0, 255, 0)) cv2.rectangle(image, (120, 120), (80, 80), (255, 0, 0), thickness=-1) cv2.rectangle(image, (140, 200), (200, 140), (0, 0, 255), thickness=5) cv2.namedWindow('rect', 1) cv2.imshow('rect', image) cv2.waitKey(0) cv2.destroyAllWindows()
利用鼠标回调函数交互式画矩形框
# -*- coding: utf-8 -*- import copy import cv2 import numpy as np WIN_NAME = 'draw_rect' class Rect(object): def __init__(self): self.tl = (0, 0) self.br = (0, 0) def regularize(self): """ make sure tl = TopLeft point, br = BottomRight point """ pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1])) pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1])) self.tl = pt1 self.br = pt2 class DrawRects(object): def __init__(self, image, color, thickness=1): self.original_image = image self.image_for_show = image.copy() self.color = color self.thickness = thickness self.rects = [] self.current_rect = Rect() self.left_button_down = False @staticmethod def __clip(value, low, high): """ clip value between low and high Parameters ---------- value: a number value to be clipped low: a number low limit high: a number high limit Returns ------- output: a number clipped value """ output = max(value, low) output = min(output, high) return output def shrink_point(self, x, y): """ shrink point (x, y) to inside image_for_show Parameters ---------- x, y: int, int coordinate of a point Returns ------- x_shrink, y_shrink: int, int shrinked coordinate """ height, width = self.image_for_show.shape[0:2] x_shrink = self.__clip(x, 0, width) y_shrink = self.__clip(y, 0, height) return (x_shrink, y_shrink) def append(self): """ add a rect to rects list """ self.rects.append(copy.deepcopy(self.current_rect)) def pop(self): """ pop a rect from rects list """ rect = Rect() if self.rects: rect = self.rects.pop() return rect def reset_image(self): """ reset image_for_show using original image """ self.image_for_show = self.original_image.copy() def draw(self): """ draw rects on image_for_show """ for rect in self.rects: cv2.rectangle(self.image_for_show, rect.tl, rect.br, color=self.color, thickness=self.thickness) def draw_current_rect(self): """ draw current rect on image_for_show """ cv2.rectangle(self.image_for_show, self.current_rect.tl, self.current_rect.br, color=self.color, thickness=self.thickness) def onm ouse_draw_rect(event, x, y, flags, draw_rects): if event == cv2.EVENT_LBUTTONDOWN: # pick first point of rect print('pt1: x = %d, y = %d' % (x, y)) draw_rects.left_button_down = True draw_rects.current_rect.tl = (x, y) if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE: # pick second point of rect and draw current rect draw_rects.current_rect.br = draw_rects.shrink_point(x, y) draw_rects.reset_image() draw_rects.draw() draw_rects.draw_current_rect() if event == cv2.EVENT_LBUTTONUP: # finish drawing current rect and append it to rects list draw_rects.left_button_down = False draw_rects.current_rect.br = draw_rects.shrink_point(x, y) print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0], draw_rects.current_rect.br[1])) draw_rects.current_rect.regularize() draw_rects.append() if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN: # pop the last rect in rects list draw_rects.pop() draw_rects.reset_image() draw_rects.draw() if __name__ == '__main__': image = np.zeros((256, 256, 3), np.uint8) draw_rects = DrawRects(image, (0, 255, 0), 2) cv2.namedWindow(WIN_NAME, 0) cv2.setMouseCallback(WIN_NAME, onm ouse_draw_rect, draw_rects) while True: cv2.imshow(WIN_NAME, draw_rects.image_for_show) key = cv2.waitKey(30) if key == 27: # ESC break cv2.destroyAllWindows()
一个简单的但是有问题的例子
# -*- coding: utf-8 -*- import cv2 import numpy as np drawing = False #是否开启画图 drawmode = True # True 矩形 False 圆形 ix,iy = -1,-1 def draw_circle(event,x,y,flags,param): global ix,iy,drawing,drawmode if event==cv2.EVENT_FLAG_LBUTTON:#左键按下 drawing = True ix, iy = x, y elif event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON:#左键按下和移动 if drawing==True: if drawmode==True: cv2.rectangle(img,(ix,iy),(x,y),(0,250,0), 3,cv2.LINE_AA) else: cv2.circle(img,(x,y),3,(0,255,0),3) elif event == cv2.EVENT_FLAG_LBUTTON: drawing==False img = np.zeros((512,512,3), np.uint8) cv2.namedWindow('opencv') cv2.setMouseCallback('opencv',draw_circle) while(1): cv2.imshow('opencv',img) key=cv2.waitKey(1) if key & 0xFF == ord('q'): break elif key &0xFF == ord('m'): drawmode = not drawmode cv2.imwrite('./1.jpg',img) cv2.destroyAllWindows()
标签:draw,python,self,cv2,矩形框,opencv,rects,image,rect 来源: https://www.cnblogs.com/gooutlook/p/16138446.html