一、前言
分享一个图像上画框程序,代码转自 python opencv鼠标画矩形框之cv2.rectangle()函数 - 华域联盟
二、代码
# -*- coding: utf-8 -*-
"""
Created on Fri Jul 23 14:35:37 2021"""# -*- coding: utf-8 -*-import copy
import cv2
import numpy as npWIN_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 = pt1self.br = pt2class DrawRects(object):def __init__(self, image, color, thickness=1):self.original_image = imageself.image_for_show = image.copy()self.color = colorself.thickness = thicknessself.rects = []self.current_rect = Rect()self.left_button_down = Falseself.boxes = [] #保存好画好的框@staticmethoddef __clip(value, low, high):"""clip value between low and highParameters----------value: a numbervalue to be clippedlow: a numberlow limithigh: a numberhigh limitReturns-------output: a numberclipped value"""output = max(value, low)output = min(output, high)return outputdef shrink_point(self, x, y):"""shrink point (x, y) to inside image_for_showParameters----------x, y: int, intcoordinate of a pointReturns-------x_shrink, y_shrink: int, intshrinked 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 rectdef 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 onmouse_draw_rect(event, x, y, flags, draw_rects):if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectprint('pt1: x = %d, y = %d' % (x, y))draw_rects.left_button_down = Truedraw_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 rectdraw_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 listdraw_rects.left_button_down = Falsedraw_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.boxes.append([ draw_rects.current_rect.tl[0], draw_rects.current_rect.tl[1], 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 listdraw_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), 1)cv2.namedWindow(WIN_NAME, 0)cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)while True:cv2.imshow(WIN_NAME, draw_rects.image_for_show)key = cv2.waitKey(30)if key == 27: # ESCbreakcv2.destroyAllWindows()print( draw_rects.boxes )
三结果
运行,可在黑色图像上画2个框,并得到2个框的左上角和右下角坐标