《OpenCV 基础全攻略:从入门到精通》
- 一、OpenCV 简介
- (一)特点
- (二)优势
- (三)应用场景
- 二、安装与配置
- 三、OpenCV 函数详解
- 1. 图像读取函数 cv2.imread ()
- 2. 图像显示函数 cv2.imshow ()
- 3. 图像保存函数 cv2.imwrite ()
- 四、基本教程
- 1. opencv 配置
- 2. 加载、修改、显示及保存图像
- 3. 图像像素及掩膜操作详解
- 4. Mat 对象
- 五、应用教程
- 1. 摄像头基本操作
- 2. 彩色目标追踪(Camshift)
- 3. 光流(optical flow)
- 4. 点追踪(lkdemo)
- 六、基础运用
- 1. 读取图像
- 2. 显示图像
- 3. 写入图像
- 4. 访问图像
- 5. 改变图像大小
- 七、基础概念介绍
- 1. 像素的数据类型
- 2. OpenCV 模块介绍
- 一、core 模块
- 二、imgproc 模块
- 三、video 模块
- 四、calib3d 模块
- 五、features2d 模块
- 六、objdetect 模块
- 七、highgui 模块
- 八、gpu 模块
- 九、其他模块
- 3. cv::NAryMatIterator
- 1. 基本概念:
- 2. 构造函数:
- 3. 成员变量:
- 4. 成员函数:
- 5. 使用方法:
- 6. 应用场景:
- 八、知识讲解
- 1. 图像的加法运算
- 2. 图像融合
- 3. 图像的类型转换
- 4. 图像缩放
- 5. 图像翻转
- 九、总结
一、OpenCV 简介
OpenCV(Open Source Computer Vision Library)作为热门的计算机视觉库,自 1999 年由英特尔公司首次发布以来,在计算机视觉领域发挥着至关重要的作用。它具有诸多特点和优势,广泛应用于各个领域。
(一)特点
- 跨平台支持:OpenCV 支持多个操作系统,包括 Windows、Linux、macOS、Android 和
iOS。这使得开发者可以在不同的平台上使用相同的代码,大大提高了开发效率。 - 多语言接口:除了 C++,OpenCV 还提供了 Python、Java 和 MATLAB
等多种编程语言的接口。这使得不同编程语言的开发者都可以轻松地使用 OpenCV 进行计算机视觉和图像处理任务。 - 丰富的功能:OpenCV 包含了超过 2500
个优化的算法,涵盖了从基本的图像处理到复杂的机器学习模型。例如,在图像处理方面,它提供了滤波、边缘检测、形态学操作等算法;在视频分析方面,提供了运动检测、对象跟踪等功能;在特征检测和描述方面,提供了 SIFT、SURF、ORB 等算法;在对象检测方面,包含了人脸检测、行人检测等预训练模型;在机器学习方面,提供了各种机器学习算法,如 KNN、SVM、决策树等。 - 高效性:OpenCV 的许多核心功能都经过高度优化,能够在实时应用中高效运行。例如,在工业检测中,OpenCV
可以快速地检测产品的缺陷、进行产品分类和机器视觉等任务,提高生产效率。 - 社区支持:作为一个开源项目,OpenCV
拥有一个活跃的开发者和用户社区,提供了丰富的文档和教程。开发者可以在社区中交流经验、分享代码和解决问题,促进了 OpenCV
的不断发展和完善。
(二)优势
- 编程语言:OpenCV 基于 C++ 实现,同时提供 Python、Ruby、Matlab 等语言的接口。OpenCV-Python 是
OpenCV 的 Python API,结合了 OpenCV C++ API 和 Python 语言的最佳特性。Python
语言本身简洁易懂,结合 OpenCV 的强大功能,使得图像处理和计算机视觉的开发变得更加简单。 - 跨平台:可以在不同的系统平台上使用,包括 Windows,Linux,OS X,Android 和 iOS。基于 CUDA 和
OpenCL 的高速 GPU 操作接口也在积极开发中,进一步提高了 OpenCV 的性能和跨平台性。 - 丰富的
API:完善的传统计算机视觉算法,涵盖主流的机器学习算法,同时添加了对深度学习的支持。这使得开发者可以在一个库中完成多种任务,无需切换不同的库和工具,提高了开发效率。
(三)应用场景
- 计算机视觉:OpenCV
可用于计算机视觉任务,如目标检测、图像分类、人脸识别、姿态估计、运动估计、光流估计等。例如,在人脸识别方面,OpenCV
可以快速准确地检测和识别出图像中的人脸,广泛应用于安防监控、门禁系统等领域。 - 视频分析:OpenCV 可用于视频分析任务,如视频跟踪、行为识别、动作识别等。例如,在智能交通系统中,OpenCV
可以检测和跟踪车辆、识别车牌和行人,统计交通流量,提高交通管理效率。 - 机器学习:OpenCV
集成了各种机器学习算法,如支持向量机、随机森林、朴素贝叶斯等,可以用于图像分类、目标检测等任务。例如,在医学影像处理中,OpenCV
可以使用机器学习算法对医学图像进行分类和识别,辅助医生进行诊断。 - 医学影像处理:OpenCV 可以用于医学影像处理,如医学图像分割、医学图像配准、医学图像增强等。例如,在肺部结节检测中,OpenCV
可以通过图像分割和特征提取算法,快速准确地检测出肺部结节,提高诊断准确性。 - 自动驾驶:OpenCV 可以用于自动驾驶,如车道检测、交通标志识别、障碍物检测等。例如,在自动驾驶汽车中,OpenCV
可以实时检测车道线、交通标志和障碍物,为汽车提供导航和安全保障。 - 工业检测:OpenCV 可以用于工业检测,如缺陷检测、产品分类、机器视觉等。例如,在电子产品制造中,OpenCV
可以检测产品的外观缺陷,提高产品质量。 - 游戏开发:OpenCV 可以用于游戏开发,如虚拟现实、增强现实等。例如,在增强现实游戏中,OpenCV
可以通过摄像头实时捕捉现实场景,将虚拟物体与现实场景融合,提供更加真实的游戏体验。
二、安装与配置
- 在 pycharm 中的安装 在 Pycharm 中安装 OpenCV 有多种方法。 一种方法是直接在 Pycharm 中进行安装。进入
Pycharm 后,选择 “File”——“Settings”,然后选择 “Project Interpreter” 右上方的符号
“+”。在搜索框中输入 opencv,选择 py-opencv,如下显示 “installing”,等待安装即可。 - 使用 pip 安装。在命令行中执行 “pip install python-opencv”。但在网络距离美国较远的情况下,或 PIP
版本未达到要求的情况下,可能会安装失败。解决方法有:一是重试;二是使用科学方法,但要注意使用科学方法的端口问题,切记不要和本地计算机使用同一个端口,容易造成
Pycharm 未知错误;三是手动去官网下载文件。有两种类型的手动安装文件,setup.py 和 XXXX.whl。这两种文件都可以通过
Pycharm 的命令行工具直接 cd 到目录进行直接安装。方法一是 “python setup.py install”,pip
安装较为简单;方法二是 “pip install C:windows/system/001/002.whl”,后面的路径为
XXXX.whl 文件的所在地址,如果地址不知道,可以通过属性查看。 - 安装成功后,可以通过以下代码段进行验证:
import numpy as np
import cv2 as cv
original = cv.imread('gongjiaoka.jpg')
grayImg = cv.imread('gongjiaoka.jpg', cv.IMREAD_GRAYSCALE)
cv.imwrite('mygray.jpg', grayImg)
cv.imshow('mygray.jpg',grayImg)
cv.imshow('gongjiaoka.jpg',original)
cv.waitKey(0)
三、OpenCV 函数详解
1. 图像读取函数 cv2.imread ()
- 参数介绍:
- cv2.imread () 函数用于读取图像文件,它有两个主要参数。第一个参数是要读入图片的完整路径,比如
“dot.jpg”。第二个参数是读入方式,有三种选择:- cv2.IMREAD_COLOR:默认参数,以彩色模式读取图像,忽略 alpha 通道。对应的数值是
1。此模式下读取的图像是一个三维数组,前两维表示图像的像素坐标,最后一维表示图像的颜色通道(通常是 BGR 三个通道)。 - cv2.IMREAD_GRAYSCALE:以灰度模式读取图像,将图像转换为单通道灰度图像。对应的数值是
0。读取后的图像是一个二维数组,每个元素表示对应像素的灰度值。 cv2.IMREAD_UNCHANGED:读取包括 alpha
通道在内的所有图像信息。对于带有 alpha 通道的图像(如 PNG 图像),将保持完整信息。对应的数值是
-1。这种模式下读取的图像可能是一个四维数组,前两维表示像素坐标,第三维表示颜色通道,第四维表示 alpha 通道(透明度信息)。
- cv2.IMREAD_COLOR:默认参数,以彩色模式读取图像,忽略 alpha 通道。对应的数值是
- cv2.imread () 函数用于读取图像文件,它有两个主要参数。第一个参数是要读入图片的完整路径,比如
- 代码示例:img = cv2.imread
(‘dot.jpg’,cv2.IMREAD_COLOR)。此代码将以彩色模式读取名为‘dot.jpg’的图像,并将其存储在变量 img
中,img 是一个 numpy 数组,可用于后续的图像处理操作。
2. 图像显示函数 cv2.imshow ()
- 参数介绍: cv2.imshow ()
函数用于显示图像,它有两个参数。第一个参数是显示图像的窗口的名字,这个名字可以是任意字符串,用于唯一标识一个窗口。例如,可以命名为
“显示图”。第二个参数是要显示的图像,通常是一个 numpy 数组,表示图像的像素数据。 - 窗口调整: cv2.WINDOW_AUTOSIZE
会根据自动图像大小调整窗口,这意味着窗口的大小会自动适应图像的尺寸,用户无法手动调整窗口大小。 cv2.WINDOW_NORMAL
允许修改窗口大小。使用此模式,用户可以通过鼠标拖动窗口边框来调整窗口的大小,以适应不同的显示需求。 - 代码示例:cv2.imshow (‘显示图’,img)。此代码将在名为 “显示图” 的窗口中显示图像
img。如果没有其他操作,窗口会一直保持显示状态,直到用户手动关闭窗口或通过代码进行关闭。
3. 图像保存函数 cv2.imwrite ()
- 参数介绍: cv2.imwrite ()
函数用于保存图像,它有两个参数。第一个参数是要保存的路径,可以是一个字符串,表示图像文件的完整路径和文件名,包括文件扩展名(如
“myimage.jpg”)。第二个参数是要保存的图像,通常是一个 numpy 数组,表示图像的像素数据。 - 代码示例:cv2.imwrite (‘path’,name_1)。此代码将图像 name_1
保存到指定的路径‘path’中。保存的图像格式由路径中的文件扩展名决定,例如,如果路径是 “myimage.jpg”,则图像将以 JPEG
格式保存。
四、基本教程
1. opencv 配置
可参考链接:https://blog.csdn.net/shuiyixin/article/details/80386022。
2. 加载、修改、显示及保存图像
- 加载图像:cv2.imread () 是 OpenCV
中用于读取图像文件的函数。它有两个主要参数,第一个参数是要读入图片的完整路径,比如
“dot.jpg”;第二个参数是读入方式,有三种选择:- cv2.IMREAD_UNCHANGED(<0)表示加载原图,不做任何改变。OpenCV 支持
JPG、PNG、TIFF等常见格式图像文件加载。 - cv2.IMREAD_GRAYSCALE(0)表示把原图作为灰度图加载进来。
- cv2.IMREAD_COLOR(>0)表示把原图作为 RGB 图像加载进来。
- cv2.IMREAD_UNCHANGED(<0)表示加载原图,不做任何改变。OpenCV 支持
- 修改图像:cv2.cvtColor ()
可把图像从一个色彩空间转换到另一个色彩空间。它具有三个参数,第一个参数是源图像,第二个参数是目标图像,第三个参数是源图像和目标图像的色彩空间转换方式,如COLOR_BGR2GRAY(从
RGB 转化到 Gray,从彩色转换为灰色)。 - 显示图像:cv2.imshow
()用于显示图像,它有两个参数。第一个参数是显示图像的窗口的名字,这个名字可以是任意字符串,用于唯一标识一个窗口;第二个参数是要显示的图像,通常是一个numpy
数组,表示图像的像素数据。窗口特性可以通过参数设置,如
WINDOW_AUTOSIZE会自动根据图像的大小调整窗口大小,不能人为改变窗口大小;WINDOW_NORMAL 允许修改窗口大小。 - 保存图像:cv2.imwrite ()
用于保存图像文件到指定目录路径。它有两个参数,第一个参数是要保存的路径,可以是一个字符串,表示图像文件的完整路径和文件名,包括文件扩展名(如 “myimage.jpg”);第二个参数是要保存的图像,通常是一个 numpy 数组,表示图像的像素数据。只有 8 位、16 位的 PNG、JPG、Tiff 文件格式而且是单通道或者三通道的 BGR 的图像才可以通过这种方式保存。保存 PNG格式的时候可以保存透明通道的图片,同时可以指定压缩参数。
3. 图像像素及掩膜操作详解
- 方法一:直接手写获取图像矩阵的宽度、高度和指针,进行像素值计算。获取图像像素指针可以通过 Mat.ptr(int i =
0) 来获取像素矩阵的指针,索引 i 表示第几行,从 0 开始计数。获取点 P (row, col) 的像素值可以通过
Mat.ptr(row)[col]。同时,还可以通过获取图像的长和宽(Mat.cols 输出图像 x 轴的像素个数,即
Width;Mat.rows 输出图像 y 轴的像素个数,即 Height;Mat.channels ()
输出每个像素点的通道个数)以及使用 saturate_cast控制像素值的取值不超过 uchar 所能表示的范围(0 -
255)。 - 方法二:使用 filter2D ()
定义掩膜进行操作。图像掩膜是用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。在
OpenCV 中,对应的 API 是 filter2D (InputArray src, OutputArray dst, int
ddepth, InputArray kernel,…)。其中 src 为输入图像,dst
为目标图像,其尺寸和通道与输入图像一致,ddepth 期望的目标图像类型,即位图深度,定义掩膜如 Mat Kernel =
(Mat(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0)。 - 显示程序运行时间:使用 getTickCount () 和 getTickFrequency ()。getTickCount ()
用于返回从操作系统启动到当前所经过的计时周期数,即计时次数;getTickFrequency () 用于返回 CPU
的频率,单位是秒,也就是一秒内重复的次数。通过总次数除以一秒内重复的次数可以得到时间(s)。
4. Mat 对象
- 拷贝:
- clone () 拷贝矩阵本身,会创建一个新的 Mat 对象,并复制原始 Mat 的数据。修改原始 Mat 不会影响深拷贝的 Mat。
- copyTo () 拷贝矩阵本身,也会创建一个新的 Mat 对象,并复制原始 Mat 的数据。复制之后 MM 与 M 完全相同,带第二参数
mask 可以进行更多控制。 - 拷贝构造函数和赋值运算符只拷贝信息头,创建一个新的 Mat 对象,这个对象与原始 Mat 共享同一数据。当原始 Mat
被修改时,浅拷贝也会反映这些更改。
- 创建 Mat 对象:多种方式创建,如指定大小、类型和初始值等。
- 使用 Mat () 构造函数,如 Mat M (2, 2, CV_8UC3, Scalar (0, 0, 255)),创建一个 2x2
的三通道矩阵,每个像素由三个元素组成,初始值为 Scalar (0, 0, 255)。 - 在 C/C++ 中构造函数进行初始化,如 int sz [3] = {2, 2, 2 };Mat L (3, sz, CV_8UC,
Scalar::all (0)),创建一个超过两维的矩阵。 - 为已存在的 IplImage 指针创建信息头,如 IplImage* img = cvLoadImage (“1.jpg”,1);Mat
mtx (img),将 IplImage 转换为 Mat(在 OpenCV3.0 版本应使用 Mat mat = cvarrToMat
(img))。 - 利用 Mat 类中的 Create () 函数,如 M.create (4,4, CV_8UC
(2)),不能为矩阵设置初始值,只是在改变尺寸时重新为矩阵数据开辟内存。 - 采用 Matlab 式的初始化,如 Mat E = Mat::eye (4,4, CV_64F) 创建一个 4x4 的单位矩阵;Mat X
= Mat::ones (2,2, CV_32F) 创建一个 2x2 的全 1 矩阵;Mat Z = Mat::zeros (3,3, CV_8UC1) 创建一个 3x3 的全 0 矩阵。 - 对小矩阵使用逗号分隔式初始化函数,如 Mat C = (Mat(3,3) <<
0,-1,0,-1,5,-1,0,-1,0)。 - 使用成员函数 clone () 或者 copyTo () 为一个已存在的 Mat 对象创建一个新的信息头。
- 使用 Mat () 构造函数,如 Mat M (2, 2, CV_8UC3, Scalar (0, 0, 255)),创建一个 2x2
- 格式化打印:调用 randu () 对矩阵填充随机数。(此处可根据实际需求进一步扩展描述如何使用 randu () 函数进行格式化打印)
- 颜色空间缩减:用特定值代替一定范围内的值。(此处可进一步解释颜色空间缩减的具体应用场景和方法)
五、应用教程
1. 摄像头基本操作
可参考链接:https://blog.csdn.net/shuiyixin/article/details/82949396。OpenCV 通过 VideoCapture 类,来对视频进行读取,调用摄像头。读取视频可以使用 VideoCapture capture;Capture.open (“1.avi”) 或者 VideoCapture capture (“1.avi”);打开 / 关闭摄像头:打开摄像头可以使用 VideoCapture capture (0)(括号内为摄像头设备号,0 表默认内置摄像头)或者 VideoCapture capture;capture.open (0);关闭摄像头使用 capture.release ()。摄像头调参方面,可以使用 isOpened () 判断摄像头是否成功初始化,open () 函数可以通过摄像头打开视频,默认为 0,如果是带前置摄像头的电脑,一般为前置摄像头。视频帧的读取可以通过 VideoCapture& VideoCapture::operator>>(Mat& image) 或者 bool VideoCapture::read (Mat& image),其中 read () 函数结合 VideoCapture::grab () 和 VideoCapture::retrieve () 其中之一被调用,用于捕获、解码和返回下一个视频帧。假如没有视频帧被捕获(相机没有连接或者视频文件中没有更多的帧)将返回 false。
2. 彩色目标追踪(Camshift)
- 算法原理:根据鼠标框选区域的色度光谱来进行摄像头读入的视频目标的跟踪。Camshift
利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的中心位置。Camshift
的核心步骤仍然是 Meanshift,只是在距离相似性度量的基础之上,又增加了图像灰度相似性的度量。两者共同作用,实现了目标的跟踪。
具体步骤如下:
-
准备样本数据:以矩形框选区域作为示例,准备包含目标区域的样本数据集。
-
计算颜色直方图:对于给定的样本区域,计算其在 HSV 颜色空间中的颜色直方图。HSV 是一种常用的颜色空间,便于颜色的识别和处理。
-
初始化窗口和帧:在待处理的输入视频帧中选取初始的目标矩形框,并将其转换为 HSV
颜色空间的直方图。同时,创建一个与输入帧大小相同的输出帧。 -
计算反向投影图:将输入帧转换到 HSV
颜色空间,并使用计算得到的目标颜色直方图创建一个模板。然后,将模板与输入帧进行归一化互相关操作,得到一个与输入帧相同大小的反向投影图。在反向投影图中,像素值越高表示该像素点与目标颜色的相似度越大。 -
运行 Meanshift
算法:从初始目标位置开始,计算目标的质心(即均值),并将质心作为新的目标位置。重复这个过程,直到目标的位置稳定或达到最大迭代次数。 -
调整窗口大小:通过计算目标的协方差矩阵来调整窗口的大小,以适应目标的形状变化。
-
更新目标颜色直方图:取目标位置周围的像素点,重新计算其在 HSV 颜色空间中的颜色直方图。
-
显示结果:将跟踪结果显示在输出帧上,可视化跟踪效果。
-
代码实现:包括设置回调函数、创建窗口、设置滑动条等。
- 设置鼠标回调函数 onMouse (),用于响应鼠标事件,当用户在图像上框选目标区域时,触发 Camshift 算法开始跟踪。
- 创建窗口 “CamShift Demo” 和 “Histogram”,分别用于显示跟踪结果和目标的颜色直方图。
- 设置滑动条 “Vmin”、“Vmax” 和 “Smin”,用于调整跟踪的参数。
- 在主循环中,首先读取视频帧,如果帧为空则退出循环。然后将帧复制到 image 中,并根据不同的条件进行处理。
- 如果 trackObject 为 1,表示已经选择了目标,进行 Camshift 算法的处理。首先计算目标区域的掩码 mask,然后创建
hue 图像,从 hsv 图像中提取 H 通道。接着,如果是用户首次选择目标,计算目标区域的颜色直方图
hist,并进行归一化处理。然后进行反向投影 calcBackProject (),并与掩码进行与操作 backproj &=
mask。最后使用 CamShift () 算法找到目标的新位置 trackBox,并在图像上绘制椭圆表示目标。 - 如果 trackObject 小于 0,表示用户正在选择目标,将选择区域进行反色处理。
- 如果 selectObject 为真且选择区域不为空,则在选择区域进行反色处理。
- 在主循环中,还处理了用户的键盘输入,包括退出程序、切换反向投影模式、显示 / 隐藏直方图、暂停视频等。
3. 光流(optical flow)
- 介绍:目前图像分析的重要方法,用来表示图像中模式的运动速度。光流的概念是 Gibson 于 1950
年提出的。所谓光流是指图像中模式运动的速度,光流场是一种二维 (2D)
瞬时速度场,其中二维速度向量是可见的三维速度向量在成像平面上的投影。光流法是把检测区域的图像变为速度的矢量场,每一个向量表示了景物中一个点在图像中位置的瞬时变化。因此,光流场携带了有关物体运动和景物三维结构的丰富信息,通过对速度场
(光流场) 的分析可以判断在检测区域内车辆的有无。
思路:求得整个图像检测区域的速度场,根据每个像素点的速度向量特征,可以对图像进行分析。如果是静止背景即无车通过时,则光流向量在整个检测区域是连续变化的;当有车通过时,光流向量必然和其邻域背景的光流向量不同,从而检测出车辆及其出现的位置。
光流法的前提假设:
- 相邻帧之间的亮度恒定值。
- 相邻视频帧的取帧的时间连续,或者相邻帧之间物体的运动比较 “微小”。
- 保持空间一致性,即,同一子图像的像素点具有相同的运动。
原理:
- 对一个连续的视频帧序列进行处理。
- 针对每一个视频序列,利用一定的目标检测方法,检测可能出现的前景目标。
- 如果某一帧出现了前景目标,找到其具有代表性的关键特征点(如 shi-Tomasi 算法)。
- 对之后的任意两个相邻视频帧而言,寻找上一帧中出现的关键特征点在当前帧中的最佳位置,从而得到前景目标在当前帧中的位置坐标。
- 如此迭代进行,便可实现目标的跟踪。
-
代码实现可以参考以下步骤:
-
使用 cvGoodFeaturesToTrack () 函数找到图像中的特征点,这是 shi-Tomasi 算法,用于 feature
-
selection,即一张图中哪些是我们感兴趣需要跟踪的点 (interest point)。
-
定义迭代算法的终止准则,使用 CvTermCriteria 结构体。
-
使用 cvCalcOpticalFlowPyrLK () 函数计算一个稀疏特征集的光流,使用金字塔中的迭代 Lucas-Kanade
方法。该函数根据给出的前一帧特征点坐标计算当前视频帧上的特征点坐标,函数寻找具有子象素精度的坐标值。
-
4. 点追踪(lkdemo)
原理:Lukas-Kanade 光学流算法。Lukas-Kanade 算法是一种基于光流的点追踪算法,通过计算图像中像素点的运动来实现点的追踪。该算法假设相邻帧之间的亮度恒定,小运动,并且空间一致。通过这些假设,可以建立光流方程,然后使用最小二乘法求解光流向量。
代码实现:包括鼠标事件处理、自动初始化跟踪等。
设置鼠标回调函数 onMouse (),用于响应鼠标事件,当用户在图像上点击时,可以添加或删除特征点。
在主循环中,首先读取视频帧,如果帧为空则退出循环。然后将帧复制到 image 中,并根据不同的条件进行处理。
如果 needToInit 为真,表示需要自动初始化跟踪,使用 goodFeaturesToTrack () 函数找到图像中的特征点,然后使用 cornerSubPix () 函数对特征点进行亚像素级精度的调整。
如果 points [0] 不为空,表示已经有特征点,使用 calcOpticalFlowPyrLK () 函数计算光流,找到特征点在当前帧中的位置。然后根据状态向量 status 和误差向量 err,筛选出有效的特征点。如果 addRemovePt 为真,表示用户正在添加特征点,并且当前点击的位置与某个特征点的距离小于 5,则将该特征点添加到 points [1] 中。如果 points [1] 的大小小于最大特征点数 MAX_COUNT,并且 addRemovePt 为真,则将当前点击的位置作为新的特征点添加到 points [1] 中。
在主循环中,还处理了用户的键盘输入,包括自动初始化跟踪、删除所有点、开启 / 关闭夜晚模式等。
六、基础运用
1. 读取图像
OpenCV 中使用cv2.imread()函数读取图像,该函数可指定读取方式。它有两个主要参数,第一个参数是要读入图片的完整路径,比如 “dot.jpg”;第二个参数是读入方式,有多种选择:
cv2.IMREAD_COLOR:默认参数,以彩色模式读取图像,忽略 alpha 通道。对应的数值是 1。此模式下读取的图像是一个三维数组,前两维表示图像的像素坐标,最后一维表示图像的颜色通道(通常是 BGR 三个通道)。
cv2.IMREAD_GRAYSCALE:以灰度模式读取图像,将图像转换为单通道灰度图像。对应的数值是 0。读取后的图像是一个二维数组,每个元素表示对应像素的灰度值。
cv2.IMREAD_UNCHANGED:读取包括 alpha 通道在内的所有图像信息。对于带有 alpha 通道的图像(如 PNG 图像),将保持完整信息。对应的数值是 -1。这种模式下读取的图像可能是一个四维数组,前两维表示像素坐标,第三维表示颜色通道,第四维表示 alpha 通道(透明度信息)。
例如:img = cv2.imread(‘example.jpg’, cv2.IMREAD_COLOR),此代码将以彩色模式读取名为‘example.jpg’的图像,并将其存储在变量 img 中,img 是一个 numpy 数组,可用于后续的图像处理操作。
2. 显示图像
OpenCV 使用cv2.imshow()在窗口中显示图像,该函数可设置窗口大小和是否可调整。它有两个参数,第一个参数是显示图像的窗口的名字,这个名字可以是任意字符串,用于唯一标识一个窗口。例如,可以命名为 “显示图”。第二个参数是要显示的图像,通常是一个 numpy 数组,表示图像的像素数据。
窗口调整有两种模式:
cv2.WINDOW_AUTOSIZE会根据自动图像大小调整窗口,这意味着窗口的大小会自动适应图像的尺寸,用户无法手动调整窗口大小。
cv2.WINDOW_NORMAL允许修改窗口大小。使用此模式,用户可以通过鼠标拖动窗口边框来调整窗口的大小,以适应不同的显示需求。
例如:cv2.imshow(‘显示图’,img)。此代码将在名为 “显示图” 的窗口中显示图像 img。如果没有其他操作,窗口会一直保持显示状态,直到用户手动关闭窗口或通过代码进行关闭。
3. 写入图像
OpenCV 使用cv2.imwrite()保存图像。它有两个参数,第一个参数是要保存的路径,可以是一个字符串,表示图像文件的完整路径和文件名,包括文件扩展名(如 “myimage.jpg”)。第二个参数是要保存的图像,通常是一个 numpy 数组,表示图像的像素数据。
例如:cv2.imwrite(‘path’,name_1)。此代码将图像 name_1 保存到指定的路径‘path’中。保存的图像格式由路径中的文件扩展名决定,例如,如果路径是 “myimage.jpg”,则图像将以 JPEG 格式保存。
4. 访问图像
访问像素值:
可通过坐标访问像素值,也可修改像素值。OpenCV 提供了多种方式访问像素值,例如:
利用指针访问:通过调用函数Mat::ptr(i)来得到第 i 行的首地址地址,然后在行内访问像素。例如:
for (int i = 0; i < Row; i++){
for (int j = 0; j < Col; j++){
Scr.ptr(i)[j][0] = 0;
}
}
利用迭代器访问:创建一个Mat::Iterator对象it,通过it = Mat::begin()来得到迭代首地址,递增迭代器直到it == Mat::end()结束迭代。例如:
while (it!= Scr.end()){
//(*it)[0] = 0;//蓝色通道置零;
//(*it)[1] = 0;//绿色通道置零;
//(*it)[2] = 0;//红色通道置零;
it++;
}
动态访问:使用at函数来得到像素,Mat::at(i,j)为一个像素点的像素值数组,是一个大小为 3 的数组。从 0 到 2 存放了 BGR 三种颜色的灰度值。例如:
for (int i = 0; i < Row; i++){
for (int j = 0; j < Col; j++){
Scr.at(i, j)[2] = 0;
}
}
访问图像属性:
包括形状、像素总数、数据类型等。可以通过以下方式访问图像属性:
image.shape:返回一个包含图像行数、列数和通道数的元组。
image.size:返回图像的像素总数。
image.dtype:返回图像的数据类型。
设置感兴趣区域(ROI):
可选择图像的特定区域进行操作。通过定义一个矩形区域的坐标,可以设置感兴趣区域。例如:
roi = image[y:y+h, x:x+w]
其中,(x,y)是矩形区域的左上角坐标,w和h分别是矩形的宽度和高度。
5. 改变图像大小
OpenCV 中图像的大小可以通过cv2.resize()函数调整:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );
参数意思:
dsize:输出图像的大小。如果这个参数不为 0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为 0,那么原图像缩放之后的大小就要通过下面的公式来计算:
fx和fy:原图像宽度和高度的缩放比例。需要注意的是dsize与fx和fy必须不能同时为零,也就是说要么dsize不为零而fx与fy同时可以为 0,要么dsize为 0 而fx与fy不同时为 0。
例如:
import cv2
image = cv2.imread(‘original.jpg’)
resized = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_LINEAR)
- 绘画图像
OpenCV 介绍多种绘画方式,如绘制直线、矩形、圆形等,以及常见参数。
绘制直线:使用cv2.line()函数。参数包括图像、起点坐标、终点坐标、颜色、线宽等。例如:
cv2.line(image, (x1,y1), (x2,y2), (255,0,0), 2);
绘制矩形:使用cv2.rectangle()函数。参数包括图像、左上角坐标、右下角坐标、颜色、线宽等。例如:
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2);
绘制圆形:使用cv2.circle()函数。参数包括图像、圆心坐标、半径、颜色、线宽等。例如:
cv2.circle(image, (x,y), radius, (0,0,255), 2);
七、基础概念介绍
1. 像素的数据类型
OpenCV 像素的数据类型以特定方式表达,如表示每个像素 8 位,无正负号,用 char 表示像素,每个像素有三个通道。
在 OpenCV 中,常见的像素数据类型包括无符号 8 位整数(CV_8U)、有符号 8 位整数(CV_8S)、无符号 16 位整数(CV_16U)、有符号 16 位整数(CV_16S)、有符号 32 位整数(CV_32S)、32 位浮点数(CV_32F)和 64 位浮点数(CV_64F)等。对于图像数据类型,还可以分为单通道和多通道。例如,CV_8UC1 表示单通道无符号 8 位整数,常用于表示二值图像或灰度图像;CV_8UC3 表示三通道无符号 8 位整数,通常对应 BGR 颜色通道的彩色图像。
2. OpenCV 模块介绍
OpenCV 包含多个模块,每个模块都有特定的功能,为计算机视觉和图像处理任务提供了丰富的工具。
一、core 模块
core 模块是 OpenCV 的核心模块,提供了基本的数据结构和函数。
基本数据结构:包括向量、矩阵和图像等。例如,cv::Mat是一个多维数组,可以表示图像、特征矩阵等。
动态数据结构:在图像处理过程中,可能需要动态调整数据结构的大小和内容。core 模块提供了一些函数来实现动态数据结构的创建和管理。
绘图函数:可以在图像上绘制各种图形,如直线、矩形、圆形等。这些绘图函数对于标注图像和可视化结果非常有用。
数组操作相关函数:包括对数组的访问、遍历、复制和修改等操作。例如,可以通过索引或迭代器访问数组中的元素,对数组进行切片操作等。
辅助功能与系统函数和宏:提供了一些辅助功能,如时间测量、错误处理和系统信息获取等。此外,还包括一些宏定义,用于方便地进行编程。
与 OpenGL 的互操作:如果需要在 OpenGL 环境中显示 OpenCV 处理后的图像,可以使用 core 模块提供的函数进行互操作。
二、imgproc 模块
imgproc 模块提供了大量的图像处理函数。
图像滤波:包括线性和非线性滤波算法。线性滤波如均值滤波、高斯滤波等,可以平滑图像,去除噪声。非线性滤波如中值滤波、双边滤波等,可以在去除噪声的同时保留图像的边缘和细节。
边缘检测:用于检测图像中的边缘信息。常见的边缘检测算法有 Canny 边缘检测、Sobel 边缘检测等。边缘检测在目标检测、图像分割等任务中起着重要作用。
形态学操作:包括膨胀、腐蚀、开运算和闭运算等。形态学操作可以用于去除噪声、填充孔洞、连接断开的边缘等。
图像分割:将图像分割成不同的区域或对象。常见的图像分割算法有阈值分割、区域生长、分水岭算法等。
直方图:用于统计图像中像素值的分布情况。可以通过直方图均衡化等方法来增强图像的对比度。
结构分析和形状描述:可以分析图像中的物体形状和结构,提取特征描述子,用于目标识别和匹配等任务。
运动分析和对象跟踪:可以分析视频中的运动信息,实现对象跟踪。例如,光流法和帧差法等算法可以用于检测和跟踪运动对象。
特征检测:检测图像中的特征点,如角点、斑点等。常用的特征检测算法有 Harris 角点检测、SIFT、SURF 和 ORB 等。
目标检测:可以检测图像中的特定目标,如人脸检测、行人检测等。通常使用级联分类器或深度学习方法进行目标检测。
三、video 模块
video 模块提供了视频处理和分析的函数。
视频的读取和保存:可以读取视频文件或从摄像头捕获视频流,并将处理后的视频保存为文件。
帧差法:通过比较连续帧之间的差异来检测运动区域。帧差法简单快速,但对于复杂的运动场景可能不够准确。
光流法:用于估计视频中像素的运动速度。光流法可以提供更准确的运动信息,但计算复杂度较高。
背景建模:可以从视频中提取背景图像,用于运动检测和目标跟踪等任务。常见的背景建模算法有高斯混合模型(GMM)和码本算法等。
运动检测和物体跟踪:可以检测视频中的运动对象,并跟踪它们的位置和运动轨迹。运动检测和物体跟踪在视频监控、智能交通等领域有广泛的应用。
四、calib3d 模块
calib3d 模块提供了摄像机标定和三维重建的函数。
摄像机标定:通过拍摄多幅已知图案的图像,计算摄像机的内参和外参,从而实现从图像坐标到世界坐标的转换。摄像机标定在三维测量、增强现实等领域非常重要。
三维重建:利用多幅图像或深度信息,重建物体的三维模型。常见的三维重建算法有三角测量、立体视觉匹配等。
多视角几何算法:用于处理多个视角下的图像,计算相机之间的相对位置和姿态,以及三维点的坐标。
物体姿态估计:根据已知的物体模型和图像中的特征点,估计物体在摄像机坐标系下的姿态。
立体相似性算法:用于计算立体图像对之间的相似性,以实现立体匹配和深度估计。
五、features2d 模块
features2d 模块提供了图像特征检测和描述子计算的函数。
特征检测:检测图像中的特征点,如角点、斑点等。常用的特征检测算法有 Harris 角点检测、SIFT、SURF 和 ORB 等。这些算法可以在不同的光照、旋转和尺度变化下保持较好的稳定性。
特征描述子计算:为每个特征点计算一个描述子,用于描述特征点的局部特征。描述子可以是向量形式,具有旋转不变性和尺度不变性。常用的描述子有 SIFT 描述子、SURF 描述子和 ORB 描述子等。
特征检测器(Feature Detectors)通用接口:提供了一种统一的接口,方便用户使用不同的特征检测算法。用户可以根据具体需求选择合适的特征检测算法,并通过通用接口进行调用。
描述符提取器(Descriptor Extractors)通用接口:类似于特征检测器通用接口,为描述符提取算法提供了统一的调用方式。
描述符匹配器(Descriptor Matchers)通用接口:用于匹配不同图像中的特征描述子,找到对应关系。常见的描述符匹配算法有暴力匹配(Brute-Force Matcher)和快速近似最近邻搜索(FLANN)等。
通用描述符(Generic Descriptor)匹配器通用接口:提供了更灵活的描述符匹配方式,可以根据不同的需求进行定制。
六、objdetect 模块
objdetect 模块提供了目标检测的功能。
Cascade Classification(级联分类):使用级联分类器进行目标检测。级联分类器是由多个弱分类器组成的强分类器,可以快速检测出目标。常见的应用有人脸检测和行人检测等。
Latent SVM:潜在支持向量机(Latent SVM)是一种基于支持向量机的目标检测算法。它可以学习到目标的外观模型,并在图像中检测出目标的位置。
七、highgui 模块
highgui 模块提供了图形用户界面(GUI)相关的函数。
图像显示和交互:可以显示图像,并处理鼠标和键盘事件。用户可以通过鼠标点击、拖动等操作与图像进行交互,实现图像标注、目标选择等功能。
摄像头和视频捕获:可以从摄像头捕获实时视频流,并进行处理和显示。同时,也可以读取视频文件进行处理。
文件读取和保存:支持图像和视频文件的读取和保存操作。可以将处理后的图像或视频保存为文件,以便后续分析和使用。
八、gpu 模块
gpu 模块包含了一些 GPU 加速的接口,底层的加速是 CUDA 实现。
利用 GPU 进行图像处理和计算可以大大提高处理速度,特别是对于大规模数据和复杂算法。
GPU 加速的函数包括图像滤波、特征检测、目标检测等。用户可以根据自己的硬件环境和需求,选择使用 GPU 加速来提高程序的性能。
九、其他模块
除了上述主要模块外,OpenCV 还包括一些其他模块,如:
ml 模块:提供了机器学习相关的函数,包括统计模型、分类算法、聚类算法等。可以用于图像分类、目标检测等任务。
flann 模块:Fast Library for Approximate Nearest Neighbors,用于在多维空间进行聚类和检索,经常和关键点匹配搭配使用。
photo 模块:主要是图像修复和降噪。可以用于去除图像中的噪声、修复损坏的区域等。
stitching 模块:图像拼接模块,有了它可以自己生成全景照片。
nonfree 模块:受到专利保护的一些算法,其实就是 SIFT 和 SURF。
contrib 模块:一些实验性质的算法,考虑在未来版本中加入的。
legacy 模块:字面是遗产,意思就是废弃的一些接口,保留是考虑到向下兼容。
ocl 模块:利用 OpenCL 并行加速的一些接口。
superres 模块:超分辨率模块,其实就是 BTV-L1(Biliteral Total Variation – L1 regularization)算法。
viz 模块:基础的 3D 渲染模块,其实底层就是著名的 3D 工具包 VTK(Visualization Toolkit)。
3. cv::NAryMatIterator
1. 基本概念:
cv::NAryMatIterator 是 OpenCV 中用于高效遍历多个多维矩阵(cv::Mat)元素的迭代器。在 OpenCV 中,cv::Mat 是一个多维数组,可以表示图像、特征矩阵等。处理多个矩阵时,通常需要逐元素地操作这些矩阵。cv::NAryMatIterator 通过简化矩阵遍历的代码,提高了代码的可读性和效率。它允许将多个矩阵看作一个整体,并以统一的方式遍历它们的元素,特别适合需要对多个矩阵进行同步操作的场景。
2. 构造函数:
cv::NAryMatIterator 的构造函数有几种常见的形式,最常用的有:
cv::NAryMatIterator::NAryMatIterator(const cv::Mat** arrays, // 输入矩阵数组的指针
cv::Mat* planes, // 存储当前遍历到的元素块的数组
int narrays = -1); // 矩阵的数量
arrays:指向输入矩阵数组的指针,每个元素都是一个 cv::Mat 对象。
planes:存储当前遍历到的每个矩阵块的指针数组。注意,它们并不是原始矩阵的拷贝,而是指向相应的内存块。
narrays:要遍历的矩阵的数量。如果为 -1,则表示 arrays 中的所有矩阵。
3. 成员变量:
const cv::Mat** arrays:指向输入矩阵的数组。
cv::Mat* planes:指向当前处理的每个矩阵块的数组。
uchar* ptr:指向当前处理的矩阵块数据的指针。
int iterdepth:表示当前遍历的维度深度。
size_t nplanes:表示矩阵的维度积(即需要遍历的块的数量)。
size_t size:表示当前处理块的大小。
4. 成员函数:
bool next():使迭代器指向下一个矩阵块。如果已经遍历完所有块,则返回 false。
cv::Mat* operator*():返回当前的矩阵块。
5. 使用方法:
以下是 cv::NAryMatIterator 的一个基本使用示例:
cv::Mat mat1 =...; // 初始化第一个矩阵
cv::Mat mat2 =...; // 初始化第二个矩阵
const cv::Mat* arrays[] = {&mat1, &mat2, nullptr };
cv::Mat planes[2];
cv::NAryMatIterator it(arrays, planes);
for (size_t i = 0; i < it.nplanes; i++, ++it) {
// 处理 planes[0] 和 planes[1]
// 它们表示 mat1 和 mat2 当前遍历到的块
}
在这个示例中,mat1 和 mat2 是两个需要同步遍历的矩阵。NAryMatIterator 将它们分块处理,planes 数组存储了当前处理的块。++it 用于移动到下一个块,而 it.nplanes 表示总块数。
6. 应用场景:
cv::NAryMatIterator 特别适合以下应用场景:
多矩阵同步操作:例如需要同时对两张图像进行像素级别的操作。
高维矩阵的遍历:例如遍历多个 3D 矩阵或更高维的矩阵。
批量操作:例如对每个图像块应用同一个操作,而不是单独处理每个矩阵的每个元素。
cv::NAryMatIterator 的设计初衷是为了简化代码的结构,避免手动处理复杂的多维索引计算,并提高代码的效率。
八、知识讲解
1. 图像的加法运算
在图像处理中,图像的加法运算是一种常见的操作。OpenCV 提供了两种主要的加法运算方式:numpy 加法运算和 OpenCV 加法运算。
numpy 加法运算:加模运算,根据情况保留结果或进行取模。例如:
import numpy as np
import cv2 as cv
img1 = cv.imread('image1.jpg')
img2 = cv.imread('image2.jpg')
result_numpy = img1 + img2
在 numpy 加法运算中,如果两个像素值相加的结果超过了 255,会进行取模操作。比如,如果两个像素值分别为 250 和 10,相加结果为 260,对于 uint8 类型的数据,260 % 256 = 4。
OpenCV 加法运算:饱和运算,超过 255 直接保留 255。例如:
result_opencv = cv.add(img1, img2)
在 OpenCV 的加法运算中,如果两个像素值相加的结果超过了 255,会直接保留 255。比如,如果两个像素值分别为 250 和 10,相加结果为 260,最终结果会被截断为 255。
代码示例:对比 numpy 和 OpenCV 的加法运算。
import numpy as np
import cv2 as cv
img1 = cv.imread('image1.jpg')
img2 = cv.imread('image2.jpg')
result_numpy = img1 + img2
result_opencv = cv.add(img1, img2)
cv.imshow('Numpy Addition', result_numpy)
cv.imshow('OpenCV Addition', result_opencv)
cv.waitKey(0)
cv.destroyAllWindows()
2. 图像融合
目的:将多张图像信息融合到一张图像上。图像融合可以将不同图像的特征或信息结合起来,创造出更丰富、更有表现力的图像。例如,可以将两张具有不同场景的图像融合在一起,以创建一个新的合成图像。
函数使用:addWeighted () 函数介绍及代码示例。
OpenCV 中的addWeighted()函数用于实现图像的线性融合。该函数的语法如下:
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);
参数解释:
src1:要叠加的第一个图像,通常是背景图像。
alpha:标识第一个参数叠加的权重。
src2:表示第二个叠加的图像,它需要和第一个数组拥有同样的尺寸和通道数。
beta:表示第二个叠加图像的权重。
gamma:输出参数,需要和前两个图像拥有同样的通道数和尺寸,一般设置为 0。
dst:输出图像。
dtype:输出阵列的深度,有默认值 -1,当两张叠加图片深度相同时,参数为 -1。
代码示例:
import cv2
img1 = cv2.imread('background.jpg')
img2 = cv2.imread('foreground.jpg')
result = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)
cv2.imshow('Image Fusion', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 图像的类型转换
包括 BGR 转灰度图像、BGR 转 RGB、灰度图像转 BGR 等。在 OpenCV 中,图像的颜色空间可以通过cv2.cvtColor()函数进行转换。例如:
BGR 转灰度图像:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)。
BGR 转 RGB:通常只在需要与非 OpenCV 库交互时才需要进行此转换,可以使用image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)。
灰度图像转 BGR:rgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)。
代码示例:使用cv2.cvtColor()进行类型转换。
import cv2
image = cv2.imread('image.jpg')
# BGR 转灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# BGR 转 RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 灰度图像转 BGR
rgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
cv2.imshow('Original Image', image)
cv2.imshow('Gray Image', gray)
cv2.imshow('RGB Image', image_rgb)
cv2.imshow('Converted RGB to BGR', rgb)
cv2.waitKey(0)
cv2.destroyAllWindows()
4. 图像缩放
函数介绍:resize 函数语法格式及参数解释。
OpenCV 中的cv2.resize()函数用于调整图像的尺寸。函数原型如下:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );
参数说明:
src:输入图像,Mat类型即可。
dst:输出图像,当其非零时,有着dsize(第三个参数)的尺寸或者有src.size()计算出来。
dsize:输出图像的大小。如果它等于 0,由下式计算:dsize = Size( round(fxsrc.cols), round(fysrc.rows));其中fx,fy,dsize都能不为 0。
fx:沿水平轴的缩放系数,默认值为 0,且等于 0 时,由下式计算:inv_scale_x =(double)dsize.width/ssize.width。
fy:沿垂直轴的缩放系数,默认值为 0,且等于 0 时,由下式计算:inv_scale_y =(double)dsize.height/ssize.height。
interpolation:用于指定插值方式,默认值为INTER_LINEAR(线性插值),可选插值方式如下:
INTER_NEAREST:最近邻插值。
INTER_LINEAR:线性插值(默认值)。
INTER_AREA:区域插值(利用像素区域关系的重采样插值)。
INTER_CUBIC:三次样条插值(超过 4×4 像素领域内的双三次插值)。
INTER_LANCZOS4:Lanczos 插值(超过 8×8 像素邻域的 Lanczos 插值)。
代码示例:不同方式的图像缩放。
import cv2
image = cv2.imread('original.jpg')
# 缩小图像尺寸为原尺寸的一半
height, width = image.shape[:2]
new_size = (width // 2, height // 2)
resized_img_linear = cv2.resize(image, new_size, interpolation=cv2.INTER_LINEAR)
# 使用区域插值缩小图像
resized_img_area = cv2.resize(image, new_size, interpolation=cv2.INTER_AREA)
# 放大图像尺寸为原尺寸的两倍
new_size_large = (width * 2, height * 2)
resized_img_cubic = cv2.resize(image, new_size_large, interpolation=cv2.INTER_CUBIC)
cv2.imshow('Original Image', image)
cv2.imshow('Resized Image (Linear)', resized_img_linear)
cv2.imshow('Resized Image (Area)', resized_img_area)
cv2.imshow('Resized Image (Cubic)', resized_img_cubic)
cv2.waitKey(0)
cv2.destroyAllWindows()
5. 图像翻转
语法:指定flipcode的值进行不同方式的翻转。
OpenCV 中使用cv2.flip()函数对图像进行翻转操作。flipcode参数决定了翻转的方式:
flipcode = 0表示上下翻转。
flipcode > 0表示左右翻转。
flipcode < 0上下 + 左右翻转。
代码示例:
import cv2
image = cv2.imread('image.jpg')
# 上下翻转
flipped_up_down = cv2.flip(image, 0)
# 左右翻转
flipped_left_right = cv2.flip(image, 1)
# 上下+左右翻转
flipped_both = cv2.flip(image, -1)
cv2.imshow('Original Image', image)
cv2.imshow('Flipped Up Down', flipped_up_down)
cv2.imshow('Flipped Left Right', flipped_left_right)
cv2.imshow('Flipped Both', flipped_both)
cv2.waitKey(0)
cv2.destroyAllWindows()
九、总结
OpenCV 作为强大的计算机视觉库,提供了丰富的功能和灵活的操作方式。通过本文的介绍,读者可以对 OpenCV 的基础有更深入的了解,为进一步的学习和应用打下坚实的基础。
在前面的章节中,我们详细介绍了 OpenCV 的各个方面,包括简介、安装与配置、函数详解、基本教程、应用教程、基础运用、基础概念介绍以及知识讲解。
OpenCV 具有跨平台支持、多语言接口、丰富的功能、高效性以及活跃的社区支持等特点和优势。它广泛应用于计算机视觉、视频分析、机器学习、医学影像处理、自动驾驶、工业检测、游戏开发等领域。
在安装与配置方面,我们介绍了在 Pycharm 中的安装方法,包括直接在 Pycharm 中安装和使用 pip 安装,以及在安装失败时的解决方法。同时,我们还通过代码示例验证了安装是否成功。
OpenCV 的函数详解部分,我们深入探讨了图像读取函数 cv2.imread ()、图像显示函数 cv2.imshow ()、图像保存函数 cv2.imwrite () 等常用函数的参数和用法。此外,我们还介绍了图像像素及掩膜操作详解、Mat 对象的拷贝和创建方法、格式化打印以及颜色空间缩减等内容。
在基本教程中,我们涵盖了 opencv 配置、加载修改显示及保存图像、图像像素及掩膜操作详解、Mat 对象等内容。同时,我们还介绍了摄像头基本操作、彩色目标追踪(Camshift)、光流(optical flow)、点追踪(lkdemo)等应用教程。
在基础运用部分,我们介绍了读取图像、显示图像、写入图像、访问图像、改变图像大小、绘画图像等内容。同时,我们还介绍了像素的数据类型、OpenCV 模块以及 cv::NAryMatIterator 等基础概念。
在知识讲解部分,我们深入探讨了图像的加法运算、图像融合、图像的类型转换、图像缩放、图像翻转等内容。
总之,OpenCV 是一个功能强大的计算机视觉库,它为开发者提供了丰富的工具和算法,使得图像处理和计算机视觉任务变得更加简单和高效。通过学习和掌握 OpenCV,我们可以在各个领域中实现各种有趣和实用的应用。