OpenCV-03 绘图功能

OpenCV(Open Source Computer Vision Library)是一个广泛应用于计算机视觉任务的开源库,提供了丰富的图像处理和计算机视觉功能。其中,绘图功能是其基础之一,允许用户在图像上绘制各种几何图形和文本。

目录

绘制直线

绘制矩形

绘制圆形

绘制椭圆

绘制多边形

绘制文本

显示绘制结果

示例源码:

运行结果

代码一些可能看不懂的地方:

常见的像素通道类型:

单通道图像:

三通道图像:

四通道图像:

通道的作用和应用:

问题3:pts = pts.reshape((-1,1,2))

为什么要重塑数组形状?

OpenCV 函数的要求:

原始数组形状:

reshape 的作用:


博客最下面有例子及每句代码的含义,可以直接运行

绘制直线

首先,让我们看看如何在图像上绘制一条直线。在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 的黑色图像(全黑)。让我详细解释一下每一部分的含义:

  1. import numpy as np: 这行代码导入了 NumPy 库,并将其命名为 np,这样在后续代码中就可以使用 np 来代替 numpy

  2. 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 表示像素值,因为它可以精确地表示颜色通道的值范围。
  3. 综合起来,np.zeros((512, 512, 3), np.uint8) 创建了一个形状为 512x512x3 的三维 NumPy 数组,其中每个元素初始化为 0。这样的数组可以用来表示一个黑色的彩色图像,因为所有像素的 RGB 值均为 (0, 0, 0),即黑色。

因此,变量 img 现在是一个大小为 512x512 的黑色图像数组,可以用来进行图像处理和计算机视觉任务。

常见的像素通道类型:

在数字图像处理中,每个像素可以包含一个或多个颜色通道的信息。这些通道决定了图像中每个像素的颜色和外观。

  1. 单通道图像
    • 灰度图像(Grayscale):这种图像只有一个通道,通常表示灰度级别。每个像素的数值表示其灰度强度,通常在 0(黑色)到 255(白色)之间,或者在更广泛的范围内表示不同的灰度级别。
  2. 三通道图像
    • RGB 图像:RGB 图像使用三个通道来表示颜色信息。
      • R(红色)通道:决定像素的红色强度。
      • G(绿色)通道:决定像素的绿色强度。
      • B(蓝色)通道:决定像素的蓝色强度。
    • 每个通道的值通常在 0 到 255 之间,组合不同强度的 R、G、B 可以生成数以百万计的颜色。
  3. 四通道图像
    • RGBA 图像:RGBA 图像与 RGB 图像类似,但增加了一个额外的 Alpha 通道。
      • R、G、B 通道:同 RGB 图像。
      • A(Alpha)通道:表示每个像素的不透明度或者透明度。通常情况下,0 表示完全透明,255 表示完全不透明,中间的值表示部分透明。
通道的作用和应用:
  • 颜色表示:RGB 通道用于表示图像中的颜色信息,允许精确地定义每个像素的颜色。
  • 图像合成:RGBA 图像中的 Alpha 通道允许将图像叠加在背景上,并控制图像的透明度。
  • 特定应用:不同的通道组合可以用于特定的图像处理任务,例如红外摄影中的 NIR(近红外)通道。

理解图像的通道结构有助于进行图像处理和计算机视觉任务,例如分割、增强、分析和合成图像。每种通道类型都有其独特的应用和优势,根据任务需要选择合适的图像格式和通道类型。

问题3:pts = pts.reshape((-1,1,2))

在这段代码中,pts = pts.reshape((-1,1,2)) 的作用是将顶点数组 pts 重新塑造为特定的形状,以便与 cv.polylines 函数兼容。具体来说,在 OpenCV 中,cv.polylines 函数要求传入一个三维的数组来表示多边形的顶点坐标。

为什么要重塑数组形状?
  1. OpenCV 函数的要求
    • cv.polylines 函数要求传入的顶点坐标数组形状为 (npts, 1, 2),其中 npts 表示顶点的数量。这种形状表示每个顶点坐标被包装在一个额外的嵌套列表中,以及每个坐标点都有两个元素(x 和 y 坐标)。
  2. 原始数组形状
    • 原始的 pts 数组是一个二维数组,形状为 (4, 2),即四个顶点,每个顶点有两个坐标。
  3. reshape 的作用
    • pts.reshape((-1, 1, 2)) 的参数 (-1, 1, 2) 中,-1 表示自动推断行数,1 表示每个顶点坐标被包装在一个单独的列表中,2 表示每个顶点坐标有两个值(x 和 y)。
    • 这样重新塑造后,pts 变成了一个三维数组,形状为 (4, 1, 2),其中:
      • 4 表示有四个顶点,
      • 1 表示每个顶点坐标被放置在一个单独的列表中,
      • 2 表示每个顶点有两个坐标值。

 关注公众号:资小库,问题快速答疑解惑

  • 20
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会写爬虫的程序员B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值