一、OpenCV 简介

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它拥有2500多个优化算法,全面融合了经典与最先进的计算机视觉和机器学习方法。这些设备可用于检测和识别人脸、识别物体、分类视频中的人类动作、追踪摄像机和物体运动、提取3D模型、将图像拼接成高分辨率全景图等多种功能。 

  • 跨平台支持:支持 Windows、Linux、macOS、Android、iOS 等多种操作系统。

  • 多语言接口:提供 C++、Python、Java 等语言的 API,其中 Python 接口因其易用性而备受欢迎。

  • 丰富的算法模块:包含超过 2500 种优化算法,涵盖图像处理、视频分析、特征检测、目标识别、3D 重建、机器学习等。

  • 高性能:底层采用 C/C++ 编写,并针对多核 CPU 和 GPU(通过 OpenCL、CUDA)进行了高度优化。

  • 活跃的社区与生态:拥有庞大的开发者社区,文档齐全,教程丰富,易于学习和集成。

二、OpenCV的安装与使用

2.1 OpenCV安装

本篇是以python和pycharm为基础来使用OpenCV,使用pip或conda语句在终端或者命令提示符中进行下载,例如:

pip install opencv-python
pip install opencv-contrib-python        
2.2 OpenCV的使用

下载完成以后就可以开始OpenCV的使用,首先来了解的是如何利用OpenCV进行图片的读取。

2.2.1 图像读取

在OpenCV中,我们一般使用 imread()语句来进行图片的读取,该函数接受图片路径作为参数,返回一个NumPy数组表示的图像数据。再使用 imshow()语句来实现内容的展示,例如:

# 图像读取
import cv2

a = cv2.imread('bread.png')
cv2.imshow('bread',a)
b = cv2.waitKey(0)
print(b)
cv2.destroyAllWindows()

print(a.shape)
print(a.dtype)
print(a.size)

其中 cv2.imread()读取 bread.png 图片,cv2.imshow()对读取到的图片进行展示,当中的参数分别为设置展示窗口的名称和需要展示的内容,cv2.waitkey()语句控制的是窗口关闭的时间,单位为 ms ,如果填 0 则需按下esc键或者点击窗口右上角的叉号。运行结果如下:

这里打印出来的值分别是按下 esc 键所代表的 ASCII 码值,图片的形状,图片的Numpy数组类型以及图像的大小。

2.2.2 视频的读取

视频的读取与图片的读取类似,只不过视频是由多张图片组成,每一帧代表一张图片,读取视频我们只需将视频中的的每一帧都读取到,然后通过 cv2.waitKey()来调节每一帧的存在时间,从而调节视频的快慢。例如:

# 视频读取
import cv2

video = cv2.VideoCapture('test.mp4')   # 0 :摄像头
if not video.isOpened():
    print("无视频")
    exit()

while True:
    ret,frame = video.read()
    if not ret:
        break
    frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    cv2.imshow('video',frame)

    if cv2.waitKey(100) == 27:
        break
video.release()
cv2.destroyAllWindows()

其中,cv2.VideoCapture()是用来接收文件路径作为参数,如果参数为 0 ,则会调用摄像头。使用 isOpened()语句检查视频是否可以正常打开。确保视频无问题后即可开始进行帧处理,我们通常会使用一个死循环来进行每一帧的读取,video.read()语句来读取每一帧,这里会返回两个值,一个是当前帧的布尔值和当前帧,所以需要两个变量来接收。如果返回的布尔值不为 True 则 break 打破循环,否则就可以进行帧的处理和展示,然后使用 cv2.waitKey()来控制每一帧的播放速度,27 代表的是 esc 的 ASCII 码值,这里整体的意思是,如果按下 esc 键,打破循环,结束视频,release()语句释放内存,最后关闭所有窗口。至此整个视频的读取就已经完成。

2.2.3 图像灰度图转换,保存,切片

在处理图片的过程中,图片会有许多色彩,这导致读取到的numpy数组过于复杂,计算量大,所以会对图片进行灰度图转换,从而减少计算量并简化图像处理流程。在OpenCV中将图片转换为灰度图的方式有使用 cv2.cvtColor()函数和 cv2.imread()直接读取。

在视频读取中出现到的 cv2.cvtColor()就是进行灰度图转换的方法之一,但这个方法不止可以转换灰度图,将 cv2.COLOR_BGR2GRAY 参数更换即可进行其他色彩转换。

而使用 cv2.imread()直接读取灰度图的方法则是在传完图片路径后增加一个参数 cv2.IMREAD_GRAYSCALE ,例如:

import cv2

a = cv2.imread('qie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('qie',a)

得到的结果如下:

如果想保存这一张灰度图,则可以使用 cv2.imwrite()来进行图片保存。

cv2.imwrite('qie_gray.png',a)

图象切片则是选取适当位置的像素范围,在所给图片中截取出这一区域进行展示。例如这里的两个企鹅的头的区域,我想要单独欣赏,就可以使用切片来实现。

# 图像切片
import cv2

a = cv2.imread('qie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('qie',a)

c = a[30:230,100:300]
d = a[100:300,350:550]
cv2.imshow('yuantu',a)
cv2.imshow('qiepian1',c)
cv2.imshow('qiepian2',d)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里需要注意,在OpenCV中横纵坐标的原点不是图片左下角,而是以图片的左上角为原点,调整选取坐标时需要仔细观察所需区域的大致位置。切片效果如下:

2.2.4 提取RGB三通道

在OpenCV中默认读取图像的格式为 BGR,在提取 RGB三通道之前需要转换为 RGB 后再分离通道或者按照BGR的顺序来分离通道。

# 提取RGB三通道
import cv2

a = cv2.imread('qie.png')

a1 = a[:,:,0]
a2 = a[:,:,1]
a3 = a[:,:,2]

b,g,r = cv2.split(a)
cv2.imshow('blue',b)
cv2.imshow('green',g)
cv2.imshow('red',r)

img = cv2.merge((a1,a2,a3))
cv2.imshow('result',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里给出了两种拆分通道的方法:

        通过NumPy数组的索引操作 a[ ::,0],a[ ::,1],a[ ::,2] 分别提取蓝色、绿色和红色通道。OpenCV默认以BGR格式读取图像,因此索引0对应蓝色通道,1对应绿色通道,2对应红色通道。

        cv2.split() 函数将图像拆分为三个独立的单通道数组,分别赋值给变量 b (蓝)、g(绿)、r(红)。这种方法与直接索引效果相同,但更直观。

使用 cv2.merge((a1,a2,a3))将分离的三个通道重新合并为完整的BGR图像。合并顺序需与原始通道顺序一致(蓝、绿、红),否则会导致颜色错乱。

注意:

  • OpenCV读取的图像数组形状为(高度,宽度,通道),通道顺序为BGR而非常见的RGB。

  • 单通道图像本质是二维矩阵,合并时需要确保各通道的尺寸一致。

  • 操作结束后需调用 cv2.waitKey()和 cv2.destroyAllWindows()来正确关闭图像窗口。

2.2.5 图像组合,打码,缩放

图像组合实现原理

图像组合的核心逻辑是通过数组切片操作将一张图片的指定区域替换为另一张图片的对应区域。OpenCV读取的图像本质上是NumPy数组,因此可以直接通过数组操作实现像素级修改。

import cv2

导入OpenCV库,用于图像处理操作。

a = cv2.imread('qie.png')
b = cv2.imread('bread.png')

使用cv2.imread()读取两张图片文件,分别存储为变量ab。这两个变量都是三维NumPy数组(高度×宽度×通道数)。

a[100:300, 200:400] = b[300:500, 400:600]

执行图像组合操作:

  • a[100:300, 200:400]:选择图像a的矩形区域,行范围100-300,列范围200-400
  • b[300:500, 400:600]:选择图像b的矩形区域,行范围300-500,列范围400-600
  • b的指定区域像素值复制到a的对应区域
cv2.imshow('a', a)
cv2.imshow('b', b)

显示修改后的图像a和原始图像bimshow()的第一个参数是窗口标题。

cv2.waitKey(0)
cv2.destroyAllWindows()

waitKey(0)保持窗口显示直到用户按键,destroyAllWindows()关闭所有OpenCV窗口。

注意:区域选择必须保证两个切片的尺寸完全一致,超出图像边界的坐标会导致错误,图像通道数(如RGB vs 灰度图)需要匹配,原始图像会被直接修改。

图像打码实现方法

图像打码通常通过将特定区域的像素替换为随机值或模糊效果来实现,保护隐私或敏感信息。以下是一个基于OpenCV的实现示例。

import cv2
import numpy as np

# 读取图像文件
a = cv2.imread('qie.png')

# 对图像特定区域进行打码
a[100:200, 200:300] = np.random.randint(0, 256, (100, 100, 3))

# 显示修改后的图像
cv2.imshow('xiugai', a)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • cv2.imread('qie.png'):加载名为qie.png的图像文件,返回一个NumPy数组表示的图像数据。

  • a[100:200, 200:300]:选择图像中从第100到200行、第200到300列的区域作为打码区域。

  • np.random.randint(0, 256, (100, 100, 3)):生成一个100x100x3的随机数组,数值范围在0到255之间(对应图像RGB/BGR通道值)。

  • cv2.imshow()显示图像窗口,waitKey(0)保持窗口直到按键,destroyAllWindows()关闭所有OpenCV窗口。

注意:打码区域坐标需确保不超过图像边界,彩色图像需处理3个通道(BGR)。

图像缩放实现方法

使用OpenCV库中的cv2.resize()函数可以实现图像缩放。

import cv2
a = cv2.imread('qie.png')
a_new = cv2.resize(a, None, fx=0.5, fy=0.5)
cv2.imshow('a', a)
cv2.imshow('a_new', a_new)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.imread('qie.png'):读取名为qie.png的图像文件,并将图像数据存储在变量a中。

cv2.resize(a, None, fx=0.5, fy=0.5):对图像进行缩放操作。参数a是输入图像,None表示不直接指定输出尺寸,而是通过fxfy指定缩放比例。fx=0.5表示宽度缩小为原来的一半,fy=0.5表示高度缩小为原来的一半。

cv2.imshow('a', a):显示原始图像,窗口标题为a

cv2.imshow('a_new', a_new):显示缩放后的图像,窗口标题为a_new

cv2.waitKey(0):等待用户按下任意键继续执行程序。

cv2.destroyAllWindows():关闭所有打开的图像窗口。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐