P3 OpenCV 图像处理
3.1 图像 读取和显示
图像处理:
1、数字图像处理: 滤波、压缩、变换。 预处理
2、计算机视觉: 从图像中获取信息。图像识别、图像跟踪。
————————
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(test)
find_package(OpenCV REQUIRED)
add_executable(test image_from_img.cpp) # 添加 可执行文件
target_link_libraries(test ${OpenCV_LIBS}) # 将 可执行文件 和 库链接
image_from_img.cpp
#include <opencv2/opencv.hpp>
int main(int argc, char** argv){
cv::Mat img = cv::imread("/home/xixi/Downloads/1.jpg");
cv::imshow("[img1]", img);
cv::waitKey(0); // 等待键盘 输入任意值 终止图像显示
return 0;
}
// 利用cv::VideoCapture可以直接访问视频文件或相机设备。
在 源码 所在文件夹 打开命令行界面
mkdir build
cd build
cmake ..
make
./test
在 OpenCV 中,图像被存储在 Mat 类中,Mat 类由矩阵头和矩阵指针组成。
- 矩阵头中存放矩阵尺寸、存储方法、存储地址等信息;
- 矩阵指针用于指向像素值被存放的具体内存区域。
Mat类非常智能,不必手动为其开辟和释放内存空间,因为 OpenCV 是采用引用机制来进行智能管理的。依据像素的通道组合和像素值编码方式,将创建不同的 Mat 对象。
cv::Point类、cv::Scalar类、cv::Size类、cv::Rect类
颜色空间转换函数cv::cvtColor()
OpenCV 中默认的图片通道存储顺序是 BGR,即蓝绿红。
- 最常见的是 RGB 颜色空间。
Mat 类的 at 方法就能遍历对应行和列坐标下的像素。
OpenCV 通过 split 函数和 merge 函数实现通道分离与通道混合。
3.2 图像 滤波
像素 之间的关联
图像滤波的目的: 在尽量保留图像特征的条件下,过滤图像中的噪声。
3.2.1 线性滤波
卷积
均值滤波、高斯滤波(高斯平滑、高斯模糊)
均值滤波由 blur 函数实现,高斯滤波由 GaussianBlur 函数实现。
均值滤波:操作简单,去噪的同时破坏了图像的细节信息,使图像变得模糊不清,所以去噪效果并不好。
高斯滤波:计算复杂一点,但是对图像中的高斯噪声有非常好的滤除效果,并且高斯噪声是普遍存在的,所以高斯滤波使用更广泛。
3.2.2 非线性滤波
椒盐噪声 使用非线性滤波会有更好的效果。
中值滤波、双边滤波
中值滤波是取窗口内的像素中值作为滤波输出值。中值滤波依靠的是排序法,用中值来近似真实值,能有效去除孤立的噪声点。
高斯滤波的窗口中的加权系数为二维高斯分布,高斯函数的取值只与空间位置有关。
双边滤波中窗口的加权系数同时与空间位置、像素值相似度有关,这样能保留细节信息的同时去除噪声。
- 空间系数
q(x, y, m, n)
和像素值相似度系数r(x, y, m, n)
中值滤波由 medianBlur 函数实现,双边滤波由 bilateralFilter 函数实现。
中值滤波能很好地去除椒盐噪声,双边滤波能保留细节的同时去除噪声。
3.2.3 形态学 滤波 【膨胀、腐蚀】
OpenCV 中最基本的形态学操作是 膨胀(dilate) 和 腐蚀(erode)。
- 膨胀是求 局部最大值 的操作
腐蚀是求 局部最小值 的操作
膨胀就是求局部最大值的操作,图像 A 与操作核 B 进行卷积,在操作核 B 的 覆盖下取区域中的最大值作为输出结果,输出结果的位置由操作核 B 的锚点决定
腐蚀就是求局部最小值的操作,图像 A 与操作核 B 进行卷积,在操作核 B 的覆盖下取区域中的最小值作为输出结果,输出结果的位置由操作核 B 的锚点决定
可以通过 morphologyEx 函数的 opt 形参取值来选择执行不同的形态学滤波算法。
形态学 操作 | 作用 | 其它 |
---|---|---|
膨胀 dilate | ||
腐蚀 erode | 去掉毛刺、孤立的像素,提取骨干信息 | |
开运算 open | 消除小物体。 去除噪点、断开狭窄的狭颈、消除细长的突出、平滑物体边界但不改变面积。 |
dilate( erode(A, B) ) 后膨胀 |
闭运算 close | 可以填充小的洞。 弥合狭窄的断裂和细长的沟壑,消除小孔,填补轮廓中的缝隙,消除噪点,连接相邻的部分。 |
erode( dilate(A, B) ) 后腐蚀 |
形态学梯度 morphgrad | 提取物体边缘 | dilate(A, B) - erode(A, B) |
顶帽运算 tophat | 突出比原轮廓 亮的部分。校正不均匀光照的影响 背景提取 |
A - open(A, B) |
黑帽运算 blackhat | 突出比原轮廓 暗的部分。校正不均匀光照的影响 | close(A, B) - A |
顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
3.3 图像 变换
3.3.1 射影变换
欧式变换: 对图像 做旋转 和 平移
相似变换: 欧式变换 + 缩放
仿射变换: 将相似变换中的缩放扩展为 非均匀缩放。
射影变换: 三维空间中的图像, 公共点进行中心投影。 【最一般的,其它是特例】
重映射方式 | 二维 自由度 | 3 维 自由度 | |
---|---|---|---|
欧式变换 | 3:旋转 θ,x方向平移,y方向平移 | 6:平移的自由度是3(xyz三个方向),旋转矩阵的自由度是3(row,pitch,yaw三个方向) | 保持线段长度、夹角不变 |
相似变换 | 4:旋转 θ,x方向平移,y方向平移和缩放因子s | 7 :3 个旋转,3 个平移,1 个缩放因子 | 角度不变、线段长度比值不变 |
仿射变换 | 6: 旋转4个,x方向平移,y方向平移 | 12 | |
射影变换 | 8 | 15 | 保持三点共线 |
- 射影变换有时又称为单应,而矩阵 H 称为
射影变换矩阵
或称为单应矩阵
。由 - 透视变换(perspective transformation)、单应性变换(homography )、直射变换(collineation)
计算 射影变换矩阵 的方法已经被封装到 OpenCV 的 getPerspectiveTransform 函数了,射影变换的实现方法被封装到 OpenCV 的 warpPerspective 函数了。
3.3.2 霍夫变换 【提取直线特征】
按法线式方程,直线用
标准霍夫变换和多尺度霍夫变换被封装在 HoughLines 函数中,而累计概率霍夫变换被封装在 HoughLinesP 函数中。由于累计概率霍夫变换拥有更高的执行效率,所以推荐直接使用累计概率霍夫变换。
3.3.3 边缘检测
常用的两种边缘检测算法是 sobel 算法和 canny 算法。
canny 算法:
1、用高斯滤波去除图像的噪声;
2、用 sobel 算法求图像的梯度幅值和方向
- 梯度方向将用于判断像素之间的连接性
3、非极大值抑制:将候选边缘像素挑选出来,排除非边缘像素;
4、最后使用滞后阈值的方式将最终的边缘像素提取出来
- 滞后阈值有两个,即高阈值和低阈值,大于高阈值的像素被保留为边缘像素,小于低阈值的像素被排除,如果像素介于两个阈值之间,且与边缘像素相连接,则会被保留下来。
5、连接强边缘像素点和与之相邻的弱边缘像素点,得到完整的边缘图像。
sobel 算法被封装到 OpenCV 的 Sobel 函数,canny 算法被封装到 OpenCV 的 Canny 函数。
3.3.4 直方图均衡
横坐标: 亮度值
纵坐标: 每个亮度值对应的像素总数量
可用于 判断两幅图的相似性。
计算直方图的方法被封装在 OpenCV 的 calcHist 函数,图像直方图均衡的方法被封装在 OpenCV 的 equalizeHist 函数。
3.4 图像 特征点提取
图像识别、图像匹配、三维重建、物体跟踪
特征点(feature point)也常常被称为关键点(key point)或兴趣点(interest point)
SIFT(scale invariant feature transform,尺度不变特征变换)特征点
SURF(Speeded Up Robust Feature,加速稳健特征)特征点
ORB(Oriented FAST and Rotated BRIEF,快速特征点提取和描述)特征点
ORB_SLAM 实时
3.4.1 SIFT(scale invariant feature transform,尺度不变特征变换)特征点
旋转尺度不变性:同一个物体,用相机在不同的角度和距离拍出来的图片,图片中物体的特征应该是一样的,不因图片的大小和旋转而改变。
1、灰度转换
2、构建高斯金字塔(gaussian pyramids),用于表示图像的尺度空间。
3、将高斯金字塔每组(octave)中相邻两图层求差值得到高斯差分金字塔(Difference of Gaussian Pyramids,DoG金字塔),用于尺度空间的极值点检测。
4、通过极值点检测、特征点定位和特征点筛选操作,提取出特征点在尺度空间的位置。
5、 回到高斯金字塔,求取该尺度空间位置上的特征点主方向以及邻域方向。
6、利用特征点的方向信息可以生成很多特征的描述子,这些特征组合成向量的形式就是特征点的描述向量,在整个提取过程的最后将输出所有特征点的描述向量。
图像金字塔
由一张张逐渐缩小的图片组合而成。金字塔最底层放置的是原始图像,然后上一层图像由下一层图像经过1/2倍降采样得到,其实就是隔点采样,这样图像尺寸会逐渐缩小
- 金字塔中含有图像的数量 n。其中,rows 和 cols 分别为原始图像的行数和列数,t 为金字塔顶层图像期望尺寸的对数值。
高斯金字塔中的图像有组(octave)和层(Layer)的概念,通过 组索引 和 层索引 可以为塔中的每个图像建立索引。
SIFT 算法的提出者 Lowe 建议将原始灰度图扩大到 2 倍大小,即通过 2 倍升采样和高斯滤波,将扩大后的图作为塔最底层的图开始构建,这样可以保留原图信息,增加特征点数量。
同一组内的图层具有相同的大小,后一个图层由前一个图层经过尺度因子为
在不同组中,后一组的第 1 个图层由前一组的倒数第 3 个图层直接经过1/2 倍降采样得到,取倒数第 3 个图层是为了保持下一步高斯差分金字塔的尺度空间连续性。
二阶导数 求最大梯度点
局部像素最大梯度点是变化最明显的点,这样的点可以作为特征点。
直接的拉普拉斯操作易受 图像噪声点 的干扰,于是引入抗干扰的高斯滤波,先进行高斯滤波,再进行拉普拉斯操作,这就是高斯拉普拉斯运算(Laplace of Gaussian,LoG)
高斯差分函数 与 尺度归一化高斯拉普拉斯函数 非常近似,因此可以用高斯差分运算替代高斯拉普拉斯运算来做图像角点的检测。
————————
特征点位置提取
在高斯差分金字塔的同一组内,图层上的极值点由该图层像素的 8 个邻域点与上下相邻图层的 9×2=18 个邻域点比较大小得到。也就是说要判断一个点是否为极值点,需要将其与周围的 26 个点比较大小
要检测全尺度下的极值点,高斯差分金字塔的每个组内要多出 2 个图层,而高斯差分金字塔是由高斯金字塔做差得到的,那么高斯金字塔的每个组内要多出 3 个图层。
- 为什么要从倒数第 3 个图层来生成下一个组的原因,即为了保持高斯差分金字塔中尺度的连续性。
特征点定位: 判断 哪一个 才是真正的 全局极值点。
Hessian 矩阵
剔除 满足 a > b, a / b > T 的边缘点。T 为 自设的阈值。
————————————
3、特征点 方向提取
特征点 主方向、特征点 邻域方向、 特征描述子。
特征点 的
计算好梯度的幅值和方向后,将方向每10° 划分一个范围,对方向进行统计,方向对应的幅度需要经过高斯系数加权后进行累计,也就是说离特征点中心越远的梯度点的幅值累计时需乘以一个越小的加权系数。
方向的 统计直方图:
横轴: 方向角度。 36个刻度。 (10° 一格)
纵轴:对应方向幅值加权累计的结果。
以 直方图峰值的方向 作为主方向,并保留大于 80% 峰值的方向作为辅方向,以增强鲁棒性。
邻域方向 与 主方向 一样
3.4.2 SURF(Speeded Up Robust Feature,加速稳健特征)特征点
SIFT: 在一般设备上 无法 实时。
SURF: 提升了 提取速度
高斯滤波 耗时
——> 基于 Hessian 矩阵的盒式滤波运算。【大幅降低运算耗时】
实现多尺度空间:在不同组上使用盒式滤波器的窗口尺寸逐渐增大;在同一组内的不同图层上使用相同窗口尺寸的盒式滤波器,但是窗口中的尺度因子取值逐渐增大。
高斯滤波:
SURF:用盒式滤波器 求出每个像素的 Hessian 矩阵。
对 盒式滤波近似 可能带来的误差 进行补偿。
SIFT 特征点位置是在 DoG [高斯差分]空间进行的
SURF 特征点位置 是在 Hessian 矩阵的 决定值 中进行。??
SURF 特征点 主方向:
统计 特征点 邻域上的 Haar小波特征。
统计 60° 扇形区域内所有 x 和 y 方向小波特征,这些特征通过高斯加权系数进行累计,即远离中心的小波特征乘上的加权系数小。然后以15° 间隔旋转 这个60°扇形区域,将整个圆遍历,统计出最大值的那个扇形方向就是特征点主方向。
SIFT: 4×4×8 = 128 维
3.4.3 ORB(Oriented FAST and Rotated BRIEF,快速特征点提取和描述)特征点
ORB 提取速度比 SURF 快 10 倍,比 SIFT 快 100 倍。
FAST(Features from Accelerated Segments Test)特征
BRIEF(Binary Robust Independent Elementary Features)描述。
1、灰度转换
2、构建 图像金字塔。降采样。拼接成大图。
- 后续 处理 基于这张 大图 ——> 尺度不变性。
旋转不变性
对给定的像素点 p,判断 p 点邻域圆周上的 16 个像素点中是否有连续 N 个点的灰度值与 p 点灰度值之差超过某一阈值,这个阈值一般设为 p 点灰度值的 20%,满足这个判断的点就是 FAST 特征点。根据 N 的具体取值,FAST 有几种不同的形态,常用的有 FAST-12、FAST-11 和 FAST-9。
计算出邻域的灰度质心 m,邻域中心 p 到灰度质心 m 的方向就是特征点的方向
高斯滤波处理
256 个 点对。 0 或 1
rBRIEF 首先在给定关键点周围的已界定 patch 中随机选择 256 个像素对,以构建 256 位向量。然后根据关键点的方向角度旋转这些随机像素对,使随机点的方向与关键点的一致。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix