首页 > 文章列表 > Python怎么用cv2动态绘制圆和矩形

Python怎么用cv2动态绘制圆和矩形

Python cv2
497 2023-04-26

Python怎么用cv2动态绘制圆和矩形

本文可以实现在指定图片上动态绘制圆和矩形。

import cv2

import numpy as np

import copy

 

class Rect(object):

 

    #创建一个类用于接收鼠标点击产生的数据坐标点。

 

    def __init__(self):

 

        self.t1 = (0,0)

 

        self.br = (0,0)

 

        self.r = 0

 

    def regularize(self):

 

        pt1 = (min(self.t1[0],self.br[0]),min(self.t1[1],self.br[1]))

 

        br1 = (max(self.t1[0],self.br[0]),max(self.t1[1],self.br[1]))

 

        self.t1 = pt1

 

        self.br = br1

 

 

class DrawRects(object):

 

    def __init__(self,img,color = (0,255,0),thickness = 3):

 

        self.img = img

 

        self.image_for_show = img.copy()

 

        '''

        用于覆盖之前的图片,然后在新的空白图片上将以前绘制的图片和目前最新的图片

        绘制的到新的图片上。

        '''

        

        self.color = color

 

        self.thickness = thickness

 

        self.left_button_down = False #用于判断左键是否按下。

 

        self.current_rect = Rect() #用于接收最新绘制的图形。

 

        self.rects = [] #用于接收绘制的矩形数据。

 

        self.circles = [] #用于接收绘制的圆数据

 

 

    @staticmethod

    def __clip(value,low,high):

 

        output = max(value,low)

 

        output = min(output,high)

 

        return output

 

    def shrink_point(self,x,y):

 

        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 reset_image(self):

 

        self.image_for_show = self.img.copy()

 

    def append(self):

 

        if draw_circle_now:

 

            self.rects.append(['c',copy.deepcopy(self.current_rect)])

 

        else:

 

            self.rects.append(['r',copy.deepcopy(self.current_rect)])

 

 

 

    def draw(self):

 

        for rect in self.rects:

 

            if rect[0] == 'r':

 

                cv2.rectangle(self.image_for_show,rect[1].t1,rect[1].br,color = self.color,thickness=self.thickness)

 

            elif rect[0] == 'c':

 

                cv2.circle(self.image_for_show,rect[1].t1,rect[1].r,color = self.color,thickness = self.thickness)

        

    def cal_R(self):

 

        self.current_rect.r = int((abs(self.current_rect.br[0] - self.current_rect.t1[0])**2 + abs(self.current_rect.br[1] - self.current_rect.t1[1])**2)**0.5)

 

        #print(self.current_circle.r)

 

        return self.current_rect.r

 

 

    def draw_current_rect(self):

 

        if draw_circle_now:

 

            self.current_rect.r = self.cal_R()

 

            cv2.circle(self.image_for_show,self.current_rect.t1,self.current_rect.r,color = self.color,thickness=3)

 

        else:

 

            cv2.rectangle(self.image_for_show,self.current_rect.t1,self.current_rect.br,

                      color = self.color,thickness = self.thickness)

 

    def pop(self):

 

        rect = Rect()

 

        if self.rects:

 

            rect = self.rects.pop()

 

        return rect

 

 

def onmouse_draw_rect(event,x,y,flags,draw_rects):

 

    if event == cv2.EVENT_LBUTTONDOWN:

 

        draw_rects.left_button_down = True

 

        draw_rects.current_rect.t1 = (x,y)

 

    if draw_rects.left_button_down  and event == cv2.EVENT_MOUSEMOVE:

 

        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:

 

        draw_rects.left_button_down = False

 

        draw_rects.current_rect.br = draw_rects.shrink_point(x,y)

 

        #draw_rects.current_rect.regularize()

 

        draw_rects.append()

 

    if (not draw_rects.left_button_down) and  event == cv2.EVENT_RBUTTONDOWN:

 

        draw_rects.pop()

 

        draw_rects.reset_image()

 

        draw_rects.draw()

 

 

 

 

draw_circle_now = False

 

img = np.zeros((516,516,3),np.uint8)

 

draw_rects = DrawRects(img,(0,255,255))

 

cv2.namedWindow('image')

 

cv2.setMouseCallback('image',onmouse_draw_rect,draw_rects)

 

while True:

 

    cv2.imshow('image',draw_rects.image_for_show)

 

    key = cv2.waitKey(30)

 

    if key == ord('c'):

 

        draw_circle_now = not draw_circle_now

 

    elif key == 27:

 

        break

 

cv2.destroyAllWindows()