python opencv鼠标画矩形框之cv2.rectangle()函数
作者:拜阳 发布时间:2022-03-12 04:33:39
关于鼠标回调函数的说明可以参考:opencv-python的鼠标交互操作
cv2.rectangle()函数说明
参数说明
导入cv2后,通过help(cv2.rectangle)可以看到函数的帮助文档如下:
rectangle(...)
rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img
. @brief Draws a simple, thick, or filled up-right rectangle.
.
. The function cv::rectangle draws a rectangle outline or a filled rectangle whose two opposite corners
. are pt1 and pt2.
.
. @param img Image.
. @param pt1 Vertex of the rectangle.
. @param pt2 Vertex of the rectangle opposite to pt1 .
. @param color Rectangle color or brightness (grayscale image).
. @param thickness Thickness of lines that make up the rectangle. Negative values, like #FILLED,
. mean that the function has to draw a filled rectangle.
. @param lineType Type of the line. See #LineTypes
. @param shift Number of fractional bits in the point coordinates.
rectangle(img, rec, color[, thickness[, lineType[, shift]]]) -> img
. @overload
.
. use `rec` parameter as alternative specification of the drawn rectangle: `r.tl() and
. r.br()-Point(1,1)` are opposite corners
其中四个参数必选:
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表示抗锯齿,线会更平滑。
注意:pt1和pt2表示任意一对对角线上的点,不一定要求pt1必需左上角,pt2必需右下角。另外pt1和pt2可以互换顺序而不影响结果。
下面是一个非交互式的程序示例
# -*- 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()
第一个矩形框pt1 = 左上角,pt2 = 右下角
第二个矩形框pt1 = 右下角,pt2 = 左上角
第三个矩形框pt1 = 右上角,pt2 = 左下角
得到的结果如下:
利用鼠标回调函数交互式画矩形框
为了容易理解下面程序,建议先参考下面文章的例2
opencv-python鼠标画点:cv2.drawMarker()
下面程序的操作方法是:
鼠标左键按下开始画当前矩形框
移动鼠标进行绘画
弹起左键当前矩形框绘画结束,并把当前矩形框加入列表
鼠标右键按下是删除矩形框列表中的最后一个对象
编程注意事项:
矩形框绘画过程中需要记录一个鼠标左键按下的状态标志。常规状态下该标志设为False,鼠标移动不进行绘画;当鼠标左键按下后,标志设为True,此时移动鼠标将进入绘画状态;左键弹起后,标志恢复False。
为了在鼠标移动过程中实时显示绘画状态,需要不停地重置用来显示的图像,并不停地重画所有已保存的矩形框
矩形框的第二个点使用shrink_point获取,确保不超出图像边界
# -*- 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 onmouse_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, onmouse_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()
终端输出:
pt1: x = 55, y = 68
pt2: x = 0, y = 0
pt1: x = 195, y = 60
pt2: x = 256, y = 0
pt1: x = 59, y = 192
pt2: x = 0, y = 256
pt1: x = 194, y = 190
pt2: x = 256, y = 256
pt1: x = 94, y = 111
pt2: x = 170, y = 168
结果如下:
来源:https://blog.csdn.net/bby1987/article/details/107302398
猜你喜欢
- 下面两个函数实现了对字符串中数字的判断。function isnaw(str) f
- 这里示范的验证码都是简单的,你也可以把字符扭曲Python第三方库无比强大,PIL 是python的一个d第三方图片处理模块,我们也可以使用
- 一、背景有些情况下,我们面对实时更新的数据,希望能够在一个窗口中可视化出来,并且能够实时更新,方便我们观察数据的变化,从而进行数据分析,例如
- 今天研究了一下JS的用setAttribute方法实现一个页面两份样式表的效果,具体方法如下:第一步:在连接样式表的元素里定义一个id,例如
- 本文实例讲述了Python基于scrapy采集数据时使用代理服务器的方法。分享给大家供大家参考。具体如下:# To authenticate
- 在日常的生活和工作中,我们经常会遇到一些大小问题,其中有很多的问题,都是可以使用一些简单的Python代码就能解决。比如不久前的复旦大佬,用
- 1.使用open()函数打开文件夹在读取一个文件的内容之前,需要先打开这个文件。在Python程序中可以通过内置函数open()来打开一个文
- 词法分析(Lexical Analysis):分析由字符组成的单词是否合法,如果没有问题的话,则产生一个单词流。 语法分析(Syntacti
- 学习目的 学会SQL中的占位符用法 在鲸鱼这几天忙死了,好几天没写了,真对不起各位。这几天让XHTML闹得不开心,虽然以前也知道这个,但没太
- 1.基本介绍在OpenCV中,图像通道是按照 B 通道→G 通道→R 通道的顺序存储的。在图像处理过程中,可以根据需要对通道进行拆分和合并。
- 初学ASP,程序是能勉强写出来了,但若每进行一次网站页面的改版,所有的源程序都将进行一次移植手术。为此所耗费的人力精力不计其数,甚至一不小心
- AXObject可用来解决IE需要激活 ActiveX 控件和生成控件调用代码 AXObjec
- 本文中的示例主要是解决在函数间不能传递多个(32个以上)参数的问题,解题的具体思路就是采用记录类型作为函数的输入和返回值,所以我们需要先定义
- 本文实例讲述了Python实现生成随机日期字符串的方法。分享给大家供大家参考,具体如下:生成随机的日期字符串,用于插入数据库。通过时间元组设
- ASP编写完整的一个IP所在地搜索类的修正文稿修正了查询方法,查询的方法和追捕的一致;只是追捕会自动更正IP。还有个函数的书写错误,也已经修
- 前言最近已经播完第一季的电视剧《雪中悍刀行》,从播放量就可以看出观众对于这部剧的期待,总播放量达到50亿,可让人遗憾的是,豆瓣评分只有5.7
- 初学python,对python的对齐很重视,为了防止出错,使用spyder工具提供的功能下面是方法:1、首先打开Tools菜单栏下的Pre
- 本文实例讲述了Python面向对象之继承原理与用法。分享给大家供大家参考,具体如下:目标单继承多继承面向对象三大特性封装 根据 职责 将 属
- Go本地测试的思路我习惯在开发过程中及时测试自己开发的功能模块,这样能及时发现问题,节省后期功能耦合之后,debug的时间。为了统一管理要测
- matplotlib制作简单的动画动画即是在一段时间内快速连续的重新绘制图像的过程.matplotlib提供了方法用于处理简单动画的绘制:i