文章目录
卷积概念
图像处理中的卷积操作是一种数学操作,用于图像增强、平滑、锐化、边缘检测等多种处理。在执行卷积操作时,会使用一个小的矩阵,称为卷积核或滤波器,这个卷积核会与图像的局部区域进行元素乘积求和的运算。
具体步骤如下:
- 选择卷积核:卷积核的大小和值根据所要执行的操作而定。常见的卷积核有用于平滑的高斯核、用于锐化的拉普拉斯核、以及用于边缘检测的Sobel核等。
- 滑动卷积核:将卷积核中心对准图像的一个像素,卷积核的其他部分会覆盖这个像素周围的区域。
- 元素乘积求和:卷积核覆盖区域的每个像素值乘以卷积核对应位置的系数,然后将所有乘积求和,得到的结果作为新图像在该中心像素位置的像素值。
- 重复操作:移动卷积核,重复上述过程,直至覆盖整个图像。
卷积操作的效果取决于卷积核的选择。例如,平滑滤波器可以减少图像噪声。
卷积核是一个小矩阵,用于在图像上滑动,并在每个位置与图像的对应区域进行加权求和,产生新的像素值。 如下图例子
卷积核为
KaTeX parse error: Undefined control sequence: \matrix at position 9: \left[ \̲m̲a̲t̲r̲i̲x̲{ 1 & 1 & 1 \…
与第一个矩阵 进行卷积
KaTeX parse error: Undefined control sequence: \matrix at position 9: \left[ \̲m̲a̲t̲r̲i̲x̲{ 12 & 13 & 1…
具体操作: 乘积求和除以中间元素 结果向下取整 中间元素4 就变成了8 然后滑动卷积核 以此类推 ,直到覆盖整个图像
卷积核一般都是奇数行的矩阵,这样可以取最中间的元素进行替换
(
12
∗
1
+
13
∗
1
+
14
∗
1
+
2
∗
1
+
4
∗
1
+
6
∗
1
+
6
∗
1
+
8
∗
1
+
10
∗
1
)
/
4
(12*1+13*1+14*1+2*1+4*1+6*1+6*1+8*1+10*1)/4
(12∗1+13∗1+14∗1+2∗1+4∗1+6∗1+6∗1+8∗1+10∗1)/4
卷积的作用
1. 图像平滑与去噪
卷积可以用来实现各种平滑滤波器(如均值滤波和高斯滤波),从而减少图像中的噪声和细节:
- 均值滤波:通过平均邻域内的像素值来平滑图像。
- 高斯滤波:使用高斯函数作为权重,对邻域内的像素进行加权平均,从而更平滑地去除噪声。
2. 边缘检测
卷积可以用来提取图像中的边缘和轮廓:
- Sobel算子:通过卷积核提取水平方向和垂直方向的边缘。
- Canny边缘检测器:使用多步卷积操作来检测图像中的强边缘。
3. 特征提取
卷积在图像特征提取中发挥着关键作用,特别是在计算机视觉和图像识别任务中:
- 方向梯度直方图(HOG):通过卷积计算图像的梯度方向和幅值。
- 尺度不变特征变换(SIFT):通过卷积检测图像中的关键点和描述符。
4. 图像增强
卷积可以用于图像的增强和锐化:
- 拉普拉斯算子:用于检测图像中的细节和边缘,通过增强边缘来提高图像的清晰度。
- 高提升滤波:通过添加原始图像和增强的图像来实现锐化效果。
常见的三种滤波
均值滤波
均值滤波的原理是使用一个固定大小的窗口(卷积核)在图像上滑动,并计算该窗口覆盖区域内所有像素值的平均值,然后用这个平均值替换窗口中心的像素值。就是一开始举的例子
数学表达式:
其中:
- (x,y)是输出图像中的像素位置。
- k是滤波器窗口的半径。
均值滤波的步骤
- 选择窗口大小:确定卷积核(窗口)的大小,常见的大小有 3×33 \times 33×3, 5×55 \times 55×5 等。
- 滑动窗口:在图像上滑动窗口,将窗口中心对准图像中的每一个像素。
- 计算平均值:计算窗口覆盖区域内所有像素的平均值。
- 替换像素值:用计算得到的平均值替换窗口中心的像素值。
- 重复操作:对图像中的每一个像素重复上述步骤,直到整个图像处理完毕。
优点和缺点
优点
- 简单实现:均值滤波算法简单,易于理解和实现。
- 平滑效果:对随机噪声有良好的平滑效果,可以有效减少图像中的高频噪声。
缺点
- 模糊边缘:均值滤波对图像的边缘也进行平滑处理,导致边缘变得模糊,不适用于需要保留边缘细节的场景。
- 处理非均匀噪声效果差:对椒盐噪声等非均匀噪声的处理效果不佳,容易被极值像素影响。
使用示例
OpenCV中均值滤波可以通过cv::blur
函数实现
函数原型
void blur(InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT);
参数说明
- src: 输入图像,必须是一个多通道的图像(如灰度图或彩色图)。
- dst: 输出图像,与输入图像具有相同的大小和类型。
- ksize: 滤波器窗口的大小,格式为
Size(width, height)
。一般为奇数。 - anchor: 锚点位置,默认值为
Point(-1, -1)
,表示锚点位于窗口的中心。 一般这个不用动 - borderType: 边界模式,用于指定边界像素的填充方式。常见的值有
BORDER_CONSTANT
,BORDER_REFLECT
,BORDER_REPLICATE
等。
上述演示卷积的过程中,可以看出最外边的一圈像素是没有被卷积的,OpenCV中可以指定把边界填充一下,这样的话,就可以把边界的像素也进行卷积处理。
示例代码
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char** argv) {
// 读取图像
cv::Mat image = cv::imread("input.jpg");
// 检查图像是否加载成功
if (image.empty()) {
std::cerr << "Error: Could not load image." << std::endl;
return -1;
}
// 定义滤波器窗口的大小
cv::Size ksize(5, 5);
// 对图像应用均值滤波
cv::Mat blurred_image;
cv::blur(image, blurred_image, ksize);
// 显示原始图像和处理后的图像
cv::imshow("Original Image", image);
cv::imshow("Blurred Image", blurred_image);
// 等待键盘输入并关闭窗口
cv::waitKey(0);
return 0;
}
效果:PS:卷积窗口越大,模糊效果越强
高斯滤波
高斯模糊是使用高斯函数定义的卷积核与图像进行卷积来实现的。高斯函数的公式为:
其中:
- σ 是标准差,控制模糊的程度,值越大模糊越强。
- x和 y是相对于卷积核中心的坐标。
这个函数很有特点,
可以看出靠近中间的位置,数值越大,越在边缘数值越小,因此可以用在带权的卷积操作
在OpenCV的C++库中,高斯模糊(Gaussian Blur)可以通过cv::GaussianBlur
函数来实现。这个函数使用高斯卷积核对图像进行卷积,从而实现平滑和降噪的效果。
cv::GaussianBlur
函数原型
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT);
参数说明
- src: 输入图像,必须是一个多通道的图像(如灰度图或彩色图)。
- dst: 输出图像,与输入图像具有相同的大小和类型。
- ksize: 高斯滤波器窗口的大小,格式为
Size(width, height)
。必须是正数和奇数。如果您希望根据sigma自动计算窗口大小,可以设置为Size(0, 0)
。 - sigmaX: X方向上的标准差。控制模糊的程度。
- sigmaY: Y方向上的标准差。如果设置为0,则其值与sigmaX相同。
- borderType: 边界模式,用于指定边界像素的填充方式。常见的值有
BORDER_CONSTANT
,BORDER_REFLECT
,BORDER_REPLICATE
等。
示例代码
以下是使用OpenCV的cv::GaussianBlur
函数进行高斯模糊的示例代码:
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char** argv) {
// 读取图像
cv::Mat image = cv::imread("input.jpg");
// 检查图像是否加载成功
if (image.empty()) {
std::cerr << "Error: Could not load image." << std::endl;
return -1;
}
// 定义滤波器窗口的大小
cv::Size ksize(15, 15);
// X方向上的标准差
double sigmaX = 3.0;
// 对图像应用高斯模糊
cv::Mat blurred_image;
cv::GaussianBlur(image, blurred_image, ksize, sigmaX);
// 显示原始图像和处理后的图像
cv::imshow("Original Image", image);
cv::imshow("Blurred Image", blurred_image);
// 等待键盘输入并关闭窗口
cv::waitKey(0);
return 0;
}
模糊效果:
中值滤波
中值滤波(Median Filtering)是一种常用的非线性滤波技术,用于去除图像中的噪声,特别是椒盐噪声(salt-and-pepper noise)。它通过将图像中每个像素值替换为其邻域像素值的中值,从而有效地保留边缘信息,同时平滑图像中的噪声。
中值滤波的基本原理
中值滤波的基本思想是对图像中的每个像素,用其邻域内所有像素值的中值来替换原像素值。中值滤波是一种非线性滤波技术,不会像均值滤波那样模糊图像中的边缘。
数学表达式
其中:
- I(x,y) 是输入图像在 (x,y)位置的像素值。
- I′(x,y)是输出图像在 (x,y) 位置的像素值。
- median{⋅} 表示邻域像素值的中值。
中值滤波的步骤
- 选择窗口大小:确定滤波器窗口的大小,如 (3 \times 3), (5 \times 5) 等。
- 滑动窗口:在图像上滑动窗口,将窗口中心对准图像中的每一个像素。
- 提取邻域像素值:将窗口内所有像素值提取出来。
- 计算中值:计算提取的像素值的中值。
- 替换像素值:用计算得到的中值替换窗口中心的像素值。
- 重复操作:对图像中的每一个像素重复上述步骤,直到整个图像处理完毕。
示例
假设我们有一个 3 * 3 的图像窗口,原始图像窗口的像素值如下:
[
10
20
30
40
50
60
70
80
90
]
\begin{bmatrix} 10 & 20 & 30 \\ 40 & 50 & 60 \\ 70 & 80 & 90 \end{bmatrix}
104070205080306090
使用3 * 3 的中值滤波器,计算其中值:
中值
=
median
{
10
,
20
,
30
,
40
,
50
,
60
,
70
,
80
,
90
}
=
50
\text{中值} = \text{median}\{10, 20, 30, 40, 50, 60, 70, 80, 90\} = 50
中值=median{10,20,30,40,50,60,70,80,90}=50
然后,用这个中值替换窗口中心的像素值50。
优点和缺点
优点
- 有效去噪:中值滤波在去除椒盐噪声方面非常有效。
- 保留边缘:中值滤波能够很好地保留图像中的边缘信息。
缺点
- 计算量大:计算中值比计算平均值需要更多的计算资源。
- 对大面积噪声效果差:对于大面积的噪声或平滑变化的噪声,中值滤波效果不如其他滤波器。
使用示例
在OpenCV中,中值滤波可以通过cv::medianBlur
函数来实现。下面是使用OpenCV进行中值滤波的C++示例代码:
示例代码
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char** argv) {
// 读取图像
cv::Mat image = cv::imread("input.jpg");
// 检查图像是否加载成功
if (image.empty()) {
std::cerr << "Error: Could not load image." << std::endl;
return -1;
}
// 定义滤波器窗口的大小
int ksize = 5; // 滤波器窗口大小必须是正奇数
// 对图像应用中值滤波
cv::Mat filtered_image;
cv::medianBlur(image, filtered_image, ksize);
// 显示原始图像和处理后的图像
cv::imshow("Original Image", image);
cv::imshow("Filtered Image", filtered_image);
// 等待键盘输入并关闭窗口
cv::waitKey(0);
return 0;
}