opencv-python实战——opencv中绘制图形与文本(万字总结,️❤️建议收藏️❤️)(代码片段)

盼小辉丶 盼小辉丶     2022-12-26     596

关键词:

0. 前言

OpenCV 作为计算机视觉库,其中一项基本功能就是绘制图形;OpenCV 提供了绘制直线、圆、矩形、椭圆等的函数。在构建计算机视觉项目时,通常希望通过绘制一些图形来显式的标注图像。例如,在人脸检测算法中,会通过绘制一个矩形,突出显示计算图像中检测到的人脸。此外,如果开发人脸识别算法,除了绘制一个矩形突出显示检测到的人脸外,通常还会绘制文本标识检测到的人脸的身份。最后,项目可能还会需要输出一些调试信息,例如,可以显示检测到的人脸数量或处理时间(用于查看算法的性能)。本文,将介绍如何使用 OpenCV 库绘制图形和文本。

1. OpenCV 绘图基础

OpenCV 提供了许多绘制基本图形的函数,包括直线、矩形和圆形等;除此之外,使用 OpenCV,也可以绘制其它更多的基本图形。图像上绘制基本形状有许多实用的场景,常见的用例主要包括:

  1. 显示算法的一些中间结果
  2. 显示算法的最终结果
  3. 显示一些调试信息

在下图中,可以看到一张绘制有矩形检测框的图像,其中实用矩形来显式的标示检测到的人脸图片(人脸检测),文本信息用于显示算法输出的其它相关的有用信息。通过这种方式,可以查看算法检测到面孔的位置:

本文中,我们将学习如何绘制具有不同颜色的基本图形和文本。为了达到这一目的,首先简要介绍下不同颜色的构建方式。我们可以构建颜色字典,使用颜色字典定义要使用的主要颜色。下表中列示了本文可能用到的颜色及其色值:

颜色名颜色值预览
blue(255, 0, 0)
green(0, 255, 0)
red(0, 0, 255)
cyan(255, 255, 0)
magenta(255, 0, 255)
yellow(0, 255, 255)
black(0, 0, 0)
white(255, 255, 255)
gray(125, 125, 125)
dark_gray(50, 50, 50)
light_gray(220, 220, 220)

由上表可以构建颜色字典如下:

colors = 'blue': (255, 0, 0), 'green': (0, 255, 0), 'red': (0, 0, 255), 'cyan': (255, 255, 0), 'magenta': (255, 0, 255), 'yellow': (0, 255, 255), 'black': (0, 0, 0), 'white': (255, 255, 255), 'gray': (125, 125, 125), 'dark_gray': (50, 50, 50), 'light_gray': (220, 220, 220), 'rand': np.random.randint(0, high=256, size=(3,)).tolist()

以上字典中定义了一些预定义的颜色,如果要使用特定颜色,例如红色 (red):

colors['red']

或者,可以使用 (0, 0, 255) 来得到红色。但是使用这个字典,不需要记住 RGB 颜色空间的色值,比数字三元组更容易使用。
除了使用字典外,另一种常见的方法是创建一个 colors_constant.py 文件来定义颜色。其中,每种颜色都由一个常量定义:

BLUE = (255, 0, 0)
GREEN = (0, 255, 0)
RED = (0, 0, 255)
YELLOW = (0, 255, 255)
MAGENTA = (255, 0, 255)
CYAN = (255, 255, 0)
LIGHT_GRAY = (220, 220, 220)
DARK_GRAY = (50, 50, 50)

在项目目录的其他文件中,可以使用以下代码使能够引用这些常量:

import colors_constant as colors
print("red: ".format(colors.RED))

此外,由于我们使用 Matplotlib 显示图形,因此我们需要通用函数 show_with_matplotlib(),其带有两个参数的,第一个是要显示的图像,第二个是要图形窗口的标题。因为必须使用 Matplotlib 显示彩色图像,因此首先需要将 BGR 图像转换为 RGB。此函数的第二步也是最后一步是使用 Matplotlib 函数显示图像:

def show_with_matplotlib(img, title):
    # 将 BGR 图像转换为 RGB
    img_RGB = img[:, :, ::-1]
    # 使用 Matplotlib 显示图形
    plt.imshow(img_RGB)
    plt.title(title)
    plt.show()

为了演示 colors 常量和 show_with_matplotlib() 函数的使用,创建 testing.py 脚本进行测试:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def show_with_matplotlib(img, title):
   # 将 BGR 图像转换为 RGB
   img_RGB = img[:, :, ::-1]
   # 使用 Matplotlib 显示图形
   plt.imshow(img_RGB)
   plt.title(title)
   plt.show()
   
# 定义颜色字典:
colors = 'blue': (255, 0, 0), 'green': (0, 255, 0), 'red': (0, 0, 255), 'yellow': (0, 255, 255),
         'magenta': (255, 0, 255), 'cyan': (255, 255, 0), 'white': (255, 255, 255), 'black': (0, 0, 0),
         'gray': (125, 125, 125), 'rand': np.random.randint(0, high=256, size=(3,)).tolist(),
         'dark_gray': (50, 50, 50), 'light_gray': (220, 220, 220)

# 创建画布
image = np.zeros((500, 500, 3), dtype="uint8")

# 修改画布背景颜色
image[:] = colors['rand']

# 利用 colors 字典绘制直线
separation = 40
for key in colors:
   cv2.line(image, (0, separation), (500, separation), colors[key], 15)
   separation += 40

# 显示图形
show_with_matplotlib(image, 'Dictionary with some predefined colors')

在上例中,创建了一个大小为 500 x 500的图像,具有 3 个通道(彩色图像),数据类型为 uint8 (8 位无符号整数),原始背景为黑色:

image = np.zeros((500, 500, 3), dtype="uint8")

如果,希望将背景颜色,例如将背景颜色修改为随机色 rand,则执行以下操作:

image[:] = colors['rand']

接下来,使用 cv2.line() 函数(这里仅作示例使用,有关此函数具体使用方式,将在下节进行详细介绍)绘制一些直线,每条线条都使用 colors 字典填充颜色。

separation = 40
for key in colors:
	cv2.line(image, (0, separation), (500, separation), colors[key], 10)
	separation += 40

最后,使用创建的 show_with_matplotlib() 函数绘制图像:

show_with_matplotlib(image, 'Dictionary with some predefined colors')

接下来,将详细介绍在 OpenCV 中基本图形的绘制。

2. OpenCV绘制图形

本节,将了解如何使用 OpenCV 函数绘制图形。首先,介绍基本图形的绘制,然后将详细介绍更高级的图形绘制。

2.1 基本图形的绘制

OpenCV 中的基本图形,包括直线、矩形和圆形等,它们是最常见和最容易绘制的形状。绘制图形的第一步是创建一个容纳绘制图形的画布。为此,将创建具有 3 个通道(以正确显示 BGR 图像)和 uint8 类型(8 位无符号整数)的 500 x 500 的黑色背景图像:

image = np.zeros((500, 500, 3), dtype="uint8")

之后使用颜色字典将背景设置为浅灰色:

image[:] = colors['gray']

一切准备就绪,接下来,我们准备绘制基本形状。需要注意的是,OpenCV 提供的大多数绘图函数都有共同的参数,因此首先总结介绍这些参数,如下表所示:

参数说明
img要绘制图形的画布图像
color用于绘制图形的颜色(BGR 三元组)
thickness如果此值为正,则为图形轮廓的粗细;否则,将绘制填充形状
lineType图形边线的类型。 OpenCV 提供了三种类型的线:cv2.LINE_4 :四连接线,cv2.LINE_8 :八连接线,cv2.LINE_AA :抗锯齿线
shift表示与定义图形的某些点的坐标相关的小数位数

上述参数中,lineTypecv2.LINE_AA 选项可产生更好的绘图质量,但绘制速度较慢。八连接线和四连接线都是非抗锯齿线,使用 Bresenham 算法绘制。而抗锯齿线使用高斯滤波算法。

2.1.1 直线

我们要了解的第一个函数是直线绘制函数 cv2.line(),函数用法如下:

img = cv2.line(img, pt1, pt2, color, thickness=1, lineType=8, shift=0)

此函数在 img 图像上画一条连接 pt1pt2 的直线:

cv2.line(image, (0, 0), (500, 500), colors['magenta'], 3)
cv2.line(image, (0, 500), (500, 0), colors['cyan'], 10)
cv2.line(image, (250, 0), (250, 500), colors['rand'], 3)
cv2.line(image, (0, 250), (500, 250), colors['yellow'], 10)

绘制图形后,调用 show_with_matplotlib(image, 'cv2.line()') 函数显示图像:

2.1.2 矩形

矩形绘制函数 cv2.rectangle() 用法如下:

img = cv2.rectangle(img, pt1, pt2, color, thickness=1, lineType=8, shift=0)

此函数根据矩形左上角点 pt1 和 右下角点 pt2 绘制矩形:

cv2.rectangle(image, (10, 50), (60, 300), colors['green'], 3)
cv2.rectangle(image, (80, 50), (130, 300), colors['blue'], -1)
cv2.rectangle(image, (150, 50), (350, 100), colors['red'], -1)
cv2.rectangle(image, (150, 150), (350, 300), colors['cyan'], 10)

绘制这些矩形后,调用 show_with_matplotlib(image, 'cv2.rectangle()') 函数显示图形:

Note:thickness 参数若为负值(例如 -1),则意味着将使用颜色填充图形。

2.1.3 圆形

圆形图形的绘制函数 cv2.circle() 用法如下:

img = cv2.circle(img, center, radius, color, thickness=1, lineType=8, shift=0)

此函数以点 center 为中心绘制一个半径为 radius 的圆:

cv2.circle(image, (50, 50), 40, colors['magenta'], 3)
cv2.circle(image, (150, 150), 40, colors['rand'], -1)
cv2.circle(image, (250, 250), 50, colors['yellow'], 5)
cv2.circle(image, (250, 250), 60, colors['yellow'], 2)
cv2.circle(image, (350, 350), 40, colors['cyan'], -2)
cv2.circle(image, (450, 450), 40, colors['blue'], 3)

绘制完这些圆形后,调用 show_with_matplotlib(image, 'cv2.circle()') 函数显示图像:

2.2 高级图形的绘制

了解了常见基本图形的绘制后,接下来将介绍如何绘制剪裁线、箭头、椭圆和折线等。同样第一步是创建一个将绘制图形的画布:

image = np.zeros((500, 500, 3), dtype="uint8")
image[:] = colors['gray']

接下来,可以开始绘制新的图形了。

2.2.1 剪裁线

剪裁线绘制函数 cv2.clipLine() 使用方法如下:

retval, pt1_new, pt2_new = cv2.clipLine(imgRect, pt1, pt2)

cv2.clipLine() 函数返回矩形内的线段(由输出点 pt1_newpt2_new 定义),该函数根据定义的矩形 imgRect 裁剪线段。如果两个原始点 pt1pt2 都在矩形之外,则 retvalFalse;否则返回 True

cv2.line(image, (0, 0), (500, 500), colors['green'], 3)
cv2.rectangle(image, (100, 100), (300, 300), colors['blue'], 3)
ret, p1, p2 = cv2.clipLine((100, 100, 300, 300), (0, 0), (300, 300))
if ret:
    cv2.line(image, p1, p2, colors['magenta'], 3)
ret, p1, p2 = cv2.clipLine((100, 100, 300, 300), (250, 150), (0, 400))
if ret:
    cv2.line(image, p1, p2, colors['cyan'], 3)

调用 show_with_matplotlib(image, 'cv2.clipLine()') 函数后,在下图中,可以看到代码运行的结果:

2.2.2 箭头

箭头绘制函数 cv2.arrowedLine() 的用法如下:

cv2.arrowedLine(img, pt1, pt2, color, thickness=1, lineType=8, shift=0, tipLength=0.1)

此函数用于绘制箭头,箭头从 pt1 定义的点指向 pt2 定义的点。箭头尖端的长度可以由 tipLength 参数控制,该参数是根据线段长度( pt1pt2 之间的距离)的百分比定义的:

# 箭头尖端的长度为线段长度的 10%
cv2.arrowedLine(image, (50, 50), (450, 50), colors['cyan'], 3, 8, 0, 0.1)
# 箭头尖端的长度为线段长度的 30%
cv2.arrowedLine(image, (50, 200), (450, 200), colors['magenta'], 3, cv2.LINE_AA, 0, 0.3)
# 箭头尖端的长度为线段长度的 30%
cv2.arrowedLine(image, (50, 400), (450, 400), colors['blue'], 3, 8, 0, 0.3)

以上代码定义了三个箭头,除了箭头的大小不同外,使用了不同的 lineType 参数 cv2.LINE_AA (也可以写 16 )和 8 (也可以写 cv2.LINE_8 ),调用 show_with_matplotlib(image, 'cv2.arrowedLine()') 函数后,可以观察它们之间的区别:

2.2.3 椭圆

绘制椭圆的函数 cv2.ellipse() 用法如下:

cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness=1, lineType=8, shift=0)

此函数用于绘制不同类型的椭圆:angle 参数(以度为单位)可以旋转椭圆;axes 参数控制长短轴的大小;startAngleendAngle 参数用于设置所需的椭圆弧(以度为单位),例如,需要完整闭合的椭圆,则 startAngle = 0endAngle = 360

cv2.ellipse(image, (100, 100), (60, 40), 0, 0, 360, colors['red'], -1)
cv2.ellipse(image, (100, 200), (80, 40), 0, 0, 360, colors['green'], 3)
cv2.ellipse(image, (100, 200), (10, 40), 0, 0, 360, colors['blue'], 3)
cv2.ellipse(image, (300, 300), (20, 80), 0, 0, 180, colors['yellow'], 3)
cv2.ellipse(image, (300, 100), (20, 80), 0, 0, 270, colors['cyan'], 3)
cv2.ellipse(image, (250, 250), (40, 40), 0, 0, 360, colors['magenta']查看详情  

opencv-python实战(番外篇)——opencvnumpy和matplotlib直方图比较(代码片段)

OpenCV-Python实战(番外篇)——OpenCV、NumPy和Matplotlib直方图比较前言OpenCV、NumPy和Matplotlib灰度直方图比较OpenCV、NumPy和Matplotlib颜色直方图比较相关链接前言在《OpenCV-Python实战(7)——直方图详解(❤️万字长... 查看详情

opencv-python实战(17)——人脸识别详解(代码片段)

OpenCV-Python实战(17)——人脸识别详解0.前言1.人脸识别简介2.使用OpenCV进行人脸识别2.1使用OpenCV进行人脸识别流程示例3.使用dlib进行人脸识别4.使用face_recognition进行人脸识别小结系列链接0.前言人脸处理是人工智能中的一... 查看详情

opencv-python实战(10)——详解opencv轮廓检测(代码片段)

OpenCV-Python实战(10)——详解OpenCV轮廓检测0.前言1.轮廓介绍2.轮廓检测3.轮廓压缩4.图像矩4.1一些基于矩的对象特征4.2Hu不变矩小结系列链接0.前言在计算机视觉领域,轮廓通常指图像中对象边界的一系列点。因此,... 查看详情

opencv-python实战(11)——opencv轮廓检测相关应用(代码片段)

OpenCV-Python实战(11)——OpenCV轮廓检测相关应用0.前言1.轮廓绘制2.轮廓筛选3.轮廓识别4.轮廓匹配小结系列链接0.前言在计算机视觉领域,轮廓通常指图像中对象边界的一系列点。因此,轮廓通常描述了对象边界的... 查看详情

opencv-python实战(13)——opencv与机器学习的碰撞(代码片段)

OpenCV-Python实战(13)——OpenCV与机器学习的碰撞0.前言1.机器学习简介1.1监督学习1.2无监督学习1.3半监督学习2.K均值(K-Means)聚类2.1K-Means聚类示例3.K最近邻3.1K最近邻示例4.支持向量机4.1支持向量机示例小结系列链接0.前言机... 查看详情

opencv-python实战(16)——人脸追踪详解(代码片段)

OpenCV-Python实战(16)——人脸追踪详解0.前言1.人脸追踪技术简介2.使用基于dlibDCF的跟踪器进行人脸跟踪2.1完整代码3.使用基于dlibDCF的跟踪器进行对象跟踪3.2完整代码小结系列链接0.前言人脸处理是人工智能中的一个热门... 查看详情

《nuitka打包实战指南》实战打包opencv-python(代码片段)

实战打包OpenCV-Python打包时解决掉的问题:ModuleNotFoundError:NoModulenamedcv2ImportError:numpy.core.multiarrayfailedtoimport打包示例源码:请看文章末尾版本信息:opencv-python==4.5.1.48numpy==1.23.2Nuitka==0.6.19.1打包系统: Windows1064位打包前我们需要... 查看详情

opencv-python实战(12)——一文详解ar增强现实(代码片段)

OpenCV-Python实战(12)——一文详解AR增强现实0.前言1.增强现实简介2.基于无标记的增强现实2.1特征检测2.2特征匹配2.3利用特征匹配和单应性计算以查找对象3.基于标记的增强现实3.1创建标记和字典3.2检测标记3.3相机校准3.4... 查看详情

opencv-python实战——opencv图像运算(❤️万字长文,含大量示例❤️)(代码片段)

OpenCV-Python实战(5)——OpenCV图像运算(❤️万字长文,含大量示例❤️)0.前言1.饱和运算2.图像加减法与图像混合3.按位运算4.形态变换4.1膨胀运算与腐蚀运算4.2开运算与闭运算4.3形态梯度运算4.4顶帽运算与... 查看详情

opencv-python实战——opencv用于图像分割的阈值技术(含大量示例,建议收藏)(代码片段)

OpenCV-Python实战(9)——OpenCV用于图像分割的阈值技术(含大量示例,建议收藏)0.前言1.阈值技术简介2.简单的阈值技术2.1阈值类型2.2简单阈值技术的实际应用3.自适应阈值算法4.Otsu阈值算法5.Triangle阈值算法6.... 查看详情

opencv-python实战——opencv简介与图像处理基础(万字总结,️建议收藏️)(代码片段)

OpenCV-Python实战(1)——OpenCV简介与图像处理基础(内含大量示例,📕建议收藏📕)OpenCV介绍Python安装OpenCVOpenCV主要模块OpenCV应用场景OpenCV图像处理基础图像基础图像处理中的主要问题图像处理流程像... 查看详情

opencv-python实战——opencv中绘制图形与文本(万字总结,️❤️建议收藏️❤️)(代码片段)

OpenCV-Python实战(3)——OpenCV中绘制图形与文本(万字总结,️📕建议收藏📕)0.前言1.OpenCV绘图基础2.OpenCV绘制图形2.1基本图形的绘制2.1.1直线2.1.2矩形2.1.3圆形2.2高级图形的绘制2.2.1剪裁线2.2.2箭头2.2.3... 查看详情

opencv-python实战——opencv常见图像处理技术(❤️万字长文,含大量示例❤️)(代码片段)

OpenCV-Python实战(4)——OpenCV常见图像处理技术(❤️万字长文,含大量示例❤️)0.前言1.拆分与合并通道2.图像的几何变换2.1缩放图像2.2平移图像2.3旋转图像2.4图像的仿射变换2.5图像的透视变换2.6裁剪图像3.... 查看详情

opencv-python实战——opencv中的色彩空间和色彩映射(❤️含大量实例,建议收藏❤️)(代码片段)

OpenCV-Python实战(6)——OpenCV中的色彩空间和色彩映射(❤️含大量示例❤️,建议收藏)0.前言1.色彩空间1.1显示色彩空间1.2不同色彩空间在皮肤分割中的不同效果2.色彩映射2.1OpenCV中的色彩映射2.2自定义色彩... 查看详情

opencv-python实战——图像与视频文件的处理(两万字详解,️建议收藏️)(代码片段)

OpenCV-Python实战(2)——图像与视频文件的处理(两万字详解,️📕建议收藏📕)0.前言1.图像与视频文件处理基础2.图像的读取与写入2.1在OpenCV中读取图像2.2使用OpenCV写入图像2.3计算机视觉项目处理流... 查看详情

opencv-python实战(14)——人脸检测详解(仅需6行代码学会4种人脸检测方法)(代码片段)

OpenCV-Python实战(14)——人脸检测详解(仅需6行代码学会4种人脸检测方法)0.前言1.人脸处理简介2.安装人脸处理相关库2.1安装dlib2.2安装face_recognition2.3安装cvlib3.人脸检测3.1使用OpenCV进行人脸检测3.1.1基于Haar级联... 查看详情

opencv-python实战——直方图详解(❤️含大量实例,建议收藏❤️)(代码片段)

OpenCV-Python实战(7)——直方图详解(❤️含大量示例,建议收藏❤️)0.前言1.直方图简介1.1直方图相关术语2.灰度直方图2.1不带蒙版的灰度直方图2.2带有蒙版的灰度直方图3.颜色直方图4.直方图的自定义可视... 查看详情