OpenCV(Open Source Computer Vision Library)是一个广泛应用于计算机视觉任务的开源库,提供了丰富的图像处理和计算机视觉功能。其中,绘图功能是其基础之一,允许用户在图像上绘制各种几何图形和文本。
目录
问题3:pts = pts.reshape((-1,1,2))
博客最下面有例子及每句代码的含义,可以直接运行
绘制直线
首先,让我们看看如何在图像上绘制一条直线。在OpenCV中,使用 cv.line()
函数可以轻松实现这一目标。以下是一个简单的示例
img = np.zeros((512, 512, 3), np.uint8) # 创建一个黑色背景的图像
# 绘制一条蓝色直线,起点(0, 0),终点(511, 511),粗细为5像素
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
绘制矩形
接下来,我们可以使用 cv.rectangle()
函数绘制矩形:
# 绘制一个红色矩形,左上角(30, 30),右下角(500, 500),边框粗细为3像素
cv.rectangle(img, (30, 30), (500, 500), (0, 0, 255), 3)
绘制圆形
OpenCV中绘制圆形使用 cv.circle()
函数:
# 绘制一个填充的红色圆形,圆心(235, 235),半径235像素
cv.circle(img, (235, 235), 235, (0, 0, 255), -1)
绘制椭圆
cv.ellipse()
函数可以绘制椭圆,可以指定旋转角度和填充类型:
# 绘制一个填充的椭圆,中心点(256, 256),长轴100像素,短轴50像素,逆时针角度0度到180度之间,颜色255(白色),-1表示填充
cv.ellipse(img, (256, 256), (100, 50), 0, 50, 180, 255, -1)
绘制多边形
如果需要绘制多边形,可以使用 cv.polylines()
函数:
# 定义多边形的顶点坐标
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
pts = pts.reshape((-1, 1, 2)) # 将顶点坐标转换为合适的形状
# 绘制一个封闭的黄色多边形,线条粗细为1像素
cv.polylines(img, [pts], True, (0, 255, 255), 1)
绘制文本
最后,我们可以在图像上绘制文本,使用 cv.putText()
函数:
# 设置要绘制的文本内容和属性
text = 'Hello, OpenCV!'
font = cv.FONT_HERSHEY_SIMPLEX
org = (50, 200) # 文本起始位置(左下角坐标)
fontScale = 2 # 字体大小因子
thickness = 3 # 文本线条粗细
color = (255, 0, 0) # 文本颜色,注意颜色顺序为BGR
# 在图像上绘制文本
cv.putText(img, text, org, font, fontScale, color, thickness)
显示绘制结果
最后,我们可以将绘制好的图像显示出来:
def openImg(img):
# 打开一个窗口,这段代码可以写也可以不写,不写打开的图片是不能改变大小的,窗口的名称必须一致,不然会打开两个
cv.namedWindow('image',cv.WINDOW_NORMAL)
# 加载显示图片
cv.imshow('image', img)
# 等待键盘输入 结束这个程序 参数0是指0毫秒,传入1000则是指1s之后继续执行代码,但是随便键盘输入也将会执行后面代码 0则是一直等待键盘输入
key = cv.waitKey(0)
# ord返回的是s按键对应的数字
if key == ord('s'):
# 按下s保存图片
cv.imwrite('test.jpg', img)
# 销毁全部窗口
cv.destroyAllWindows()
示例源码:
def openImg(img):
# 打开一个窗口,这段代码可以写也可以不写,不写打开的图片是不能改变大小的,窗口的名称必须一致,不然会打开两个
cv.namedWindow('image',cv.WINDOW_NORMAL)
# 加载显示图片
cv.imshow('image', img)
# 等待键盘输入 结束这个程序 参数0是指0毫秒,传入1000则是指1s之后继续执行代码,但是随便键盘输入也将会执行后面代码 0则是一直等待键盘输入
key = cv.waitKey(0)
# ord返回的是s按键对应的数字
if key == ord('s'):
# 按下s保存图片
cv.imwrite('test.jpg', img)
# 销毁全部窗口
cv.destroyAllWindows()
# 绘图学习
def drawing_all():
# 创建一个黑色的图像
# 第一个参数的意思是创建一个512x512的3通道的画布,画布初始化时候都为0,所以0,0,0就代表黑色
# 第二个参数是表示这组颜色在0-255之内,np.uint8 是 NumPy 中表示无符号整数(即非负整数)的数据类型,占用 8 位(即一个字节),范围从 0 到 255。在图像处理中,通常使用 np.uint8 表示像素值,因为它可以精确地表示颜色通道的值范围。
# 通道的概念,单通道表示只有黑白色调 3通道表示RGB也就是红色、绿色、蓝色 4通道加上透明度
img = np.zeros((512, 512, 3), np.uint8)
# 参数分别是,画布对象、起点、终点、颜色、粗细
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
# 参数分别是,画布对象、起点、终点、颜色、粗细 矩形只要起点坐标和对角坐标即可
cv.rectangle(img, (30, 30), (500, 500),(255, 0, 0), 3)
# 参数分别是,画布对象、圆心、半径、颜色、粗细 画⚪需要圆心和半径 -1表示圆内全部为红色
cv.circle(img,(235,235), 235, (0,0,255), -1)
# 参数分别是,画布对象、圆心、(长轴长度、短轴长度)、旋转角度、起始角度(右)、终止角度(左)、颜色、粗细
cv.ellipse(img, (256, 256), (100, 50), 0, 50, 180, 255, -1)
# 顶点坐标
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
# -1 表示自动推断行数,1 表示每个顶点坐标被包装在一个单独的列表中,2 表示每个顶点坐标有两个值(x 和 y)
# 这句代码意思是二维数组转化为三维数组
pts = pts.reshape((-1, 1, 2))
# 参数分别是,画布对象、顶点坐标、是否封闭、颜色
cv.polylines(img, [pts], True, (0, 255, 255))
# 设置要绘制的文本
text = 'Hello, OpenCV!'
# 选择字体
font = cv.FONT_HERSHEY_SIMPLEX
# 设置文本的起始位置(左下角坐标)
org = (50, 200)
# 设置字体大小和厚度
fontScale = 2
thickness = 3
# 设置文本颜色 (B, G, R)
color = (255, 0, 0) # 这里是蓝色,因为OpenCV中颜色顺序是BGR
# 在图像上绘制文本
cv.putText(img, text, org, font, fontScale, color, thickness)
openImg(img)
运行结果
代码一些可能看不懂的地方:
img = np.zeros((512,512,3), np.uint8)
这段代码是使用 Python 的 NumPy 库创建了一个 512x512 的黑色图像(全黑)。让我详细解释一下每一部分的含义:
-
import numpy as np
: 这行代码导入了 NumPy 库,并将其命名为np
,这样在后续代码中就可以使用np
来代替numpy
。 -
np.zeros((512,512,3), np.uint8)
: 这是 NumPy 的函数zeros
,用于创建一个由零组成的数组。具体解释如下:(512, 512, 3)
: 这是zeros
函数的第一个参数,指定了数组的形状。在这里,它创建了一个三维数组,大小为 512x512,并且有 3 个通道(RGB)。因此,这个数组可以表示一个 512x512 的彩色图像,每个像素有红色、绿色和蓝色三个通道的值。np.uint8
: 这是zeros
函数的第二个参数,指定了数组元素的数据类型。np.uint8
是 NumPy 中表示无符号整数(即非负整数)的数据类型,占用 8 位(即一个字节),范围从 0 到 255。在图像处理中,通常使用np.uint8
表示像素值,因为它可以精确地表示颜色通道的值范围。
-
综合起来,
np.zeros((512, 512, 3), np.uint8)
创建了一个形状为 512x512x3 的三维 NumPy 数组,其中每个元素初始化为 0。这样的数组可以用来表示一个黑色的彩色图像,因为所有像素的 RGB 值均为 (0, 0, 0),即黑色。
因此,变量 img
现在是一个大小为 512x512 的黑色图像数组,可以用来进行图像处理和计算机视觉任务。
常见的像素通道类型:
在数字图像处理中,每个像素可以包含一个或多个颜色通道的信息。这些通道决定了图像中每个像素的颜色和外观。
-
单通道图像:
- 灰度图像(Grayscale):这种图像只有一个通道,通常表示灰度级别。每个像素的数值表示其灰度强度,通常在 0(黑色)到 255(白色)之间,或者在更广泛的范围内表示不同的灰度级别。
-
三通道图像:
- RGB 图像:RGB 图像使用三个通道来表示颜色信息。
- R(红色)通道:决定像素的红色强度。
- G(绿色)通道:决定像素的绿色强度。
- B(蓝色)通道:决定像素的蓝色强度。
- 每个通道的值通常在 0 到 255 之间,组合不同强度的 R、G、B 可以生成数以百万计的颜色。
- RGB 图像:RGB 图像使用三个通道来表示颜色信息。
-
四通道图像:
- RGBA 图像:RGBA 图像与 RGB 图像类似,但增加了一个额外的 Alpha 通道。
- R、G、B 通道:同 RGB 图像。
- A(Alpha)通道:表示每个像素的不透明度或者透明度。通常情况下,0 表示完全透明,255 表示完全不透明,中间的值表示部分透明。
- RGBA 图像:RGBA 图像与 RGB 图像类似,但增加了一个额外的 Alpha 通道。
通道的作用和应用:
- 颜色表示:RGB 通道用于表示图像中的颜色信息,允许精确地定义每个像素的颜色。
- 图像合成:RGBA 图像中的 Alpha 通道允许将图像叠加在背景上,并控制图像的透明度。
- 特定应用:不同的通道组合可以用于特定的图像处理任务,例如红外摄影中的 NIR(近红外)通道。
理解图像的通道结构有助于进行图像处理和计算机视觉任务,例如分割、增强、分析和合成图像。每种通道类型都有其独特的应用和优势,根据任务需要选择合适的图像格式和通道类型。
问题3:pts = pts.reshape((-1,1,2))
在这段代码中,pts = pts.reshape((-1,1,2))
的作用是将顶点数组 pts
重新塑造为特定的形状,以便与 cv.polylines
函数兼容。具体来说,在 OpenCV 中,cv.polylines
函数要求传入一个三维的数组来表示多边形的顶点坐标。
为什么要重塑数组形状?
-
OpenCV 函数的要求:
cv.polylines
函数要求传入的顶点坐标数组形状为(npts, 1, 2)
,其中npts
表示顶点的数量。这种形状表示每个顶点坐标被包装在一个额外的嵌套列表中,以及每个坐标点都有两个元素(x 和 y 坐标)。
-
原始数组形状:
- 原始的
pts
数组是一个二维数组,形状为(4, 2)
,即四个顶点,每个顶点有两个坐标。
- 原始的
-
reshape 的作用:
pts.reshape((-1, 1, 2))
的参数(-1, 1, 2)
中,-1
表示自动推断行数,1
表示每个顶点坐标被包装在一个单独的列表中,2
表示每个顶点坐标有两个值(x 和 y)。- 这样重新塑造后,
pts
变成了一个三维数组,形状为(4, 1, 2)
,其中:4
表示有四个顶点,1
表示每个顶点坐标被放置在一个单独的列表中,2
表示每个顶点有两个坐标值。
关注公众号:资小库,问题快速答疑解惑