图像滤波
图像滤波
简介
-
“平滑处理”(smoothing)也称 “模糊处理”(bluring),是一项简单且使用频率很高的图像处理方法。平滑处理的用途有很多,最常见的是用来减少图像上的噪点或者失真。在涉及到降低图像分辨率时,平滑处理是非常好用的方法
-
图像滤波,就是在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可或缺的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性
-
图像滤波可以理解为根据图像全局或局部或两者综合的信息,为像素点赋予新值的行为
图像卷积
简介
- 图像卷积可以看成是一个卷积模板在另一个大的图像上移动,对每个卷积模板覆盖的区域进行加权平均,得到的值作为中心像素点的输出值
- 卷积首先需要将卷积模板旋转180o,之后从图像的左上角开始移动旋转后的卷积模板,从左到右,从上到下,依次进行卷积计算,最终得到卷积后的图像
- 卷积模板又称为卷积核或者内核,通常是一个方形 MxN 矩阵,其中 M 和 N 都是奇数
- 在使用卷积核对图像应用任何卷积之前,需要确保所有值都已归一化。 这是通过将卷积核中的每个元素除以卷积核中的元素数来完成的。这确保所有值都保持在 [0,1] 的范围内
均值滤波(Mean Filtering)
简介
- 均值滤波将滤波器内所有的像素值都看作中心像素值的测量,将滤波器内所有的像素值的平均值作为滤波器中心处的图像像素值
- 滤波器内的每个数据表示对应的像素在决定中心像素值的过程中所占的权重,由于滤波器内所有的像素值在决定中心像素值的过程中占有相同的权重,因此滤波器内每个数据都相等
- 均值滤波的优点是,在像素值变换趋势一致的情况下,可以将受噪声影响而突然变化的像素值修正为周围邻近像素值的平均值,去除噪声影响
- 缺点是,会缩小像素值之间的差距,使得细节信息变得更加模糊,滤波器范围越大,变模糊的效果越明显
实现
OpenCV 4 中提供了blur()
函数用于实现图像的均值滤波
blur(src, dst, ksize)
- src:待均值滤波的图像,类型必须是CV_8U、CV_16U、CV_16S、CV_32F和CV_64F这5种数据类型之一
- dst:均值滤波后的图像,与输入图像具有相同的尺寸、数据类型及通道数
- ksize:卷积核尺寸(滤波器尺寸),尺寸越大,滤波后图像变得越模糊
实现代码:
// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;
int main()
{
Mat_<Vec3b> image = imread("/home/kslas/OpenCV/wood.jpg", -1);
// Blurred using OpenCV C++ blur() function
Mat_<Vec3b> img_blur;
blur(image, img_blur, Size(5,5));
imshow("Original", image);
imshow("Blurred", img_blur);
waitKey();
destroyAllWindows();
return 0;
}
运行结果:
高斯滤波(Gaussian Filtering)
简介
-
高斯模糊根据像素值与卷积核中心的距离对像素值进行加权, 离中心较远的像素对加权平均值的影响较小
-
高斯滤波对高斯噪声去除效果较好,但是同样会对图像造成模糊,并且滤波器的尺寸越大,滤波后图像变得越模糊
-
高斯滤波的尺寸越大,标准差越大,处理过的图像模糊程度越大
实现
OpenCV 4 提供了对图像进行高斯滤波操作的GaussianBlur()
函数
GaussianBlur(src, dst, ksize, sigmaX, sigmaY)
- src:待高斯滤波图像,可以具有任意的通道数目,但数据类型必须为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F
- dst:输出图像,与输入图像src具有相同的尺寸、通道数和数据类型
- ksize:高斯滤波器的尺寸。滤波器可以不为正方形,但必须是正奇数
- sigmaX:X方向的高斯滤波器标准偏差
- sigmaY:Y方向的高斯滤波器标准偏差,默认为0
PS:若ksize不为(0, 0),则按照ksize计算,后面的sigmaX没有意义。若ksize为(0, 0),则根据后面的sigmaX计算ksize
实现代码:
// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;
int main()
{
Mat_<Vec3b> image = imread("/home/kslas/OpenCV/wood.jpg", -1);
// Performing Gaussian Blur
Mat_<Vec3b> gaussian_blur;
GaussianBlur(image, gaussian_blur, Size(5,5), 0, 0);
imshow("Original", image);
imshow("Gaussian Blurred", gaussian_blur);
waitKey();
destroyAllWindows();
return 0;
}
运行结果:
中值滤波(Median Filtering)
简介
-
中值滤波是一种非线性数字滤波器技术,经常用于去除图像或者其他信号中的噪声,是处理椒盐噪声的常用降噪算法
-
中值滤波将滤波器范围内所有的像素值按照由小到大的顺序排列,选取排序序列的中值作为滤波器中心处阴影像素的新像素值
-
在滤波器尺寸相同的情况下,中值模糊的效果比高斯模糊更突出。图像平滑里中值滤波的效果最好
-
在处理时间上,中值滤波消耗的时间要远大于均值滤波消耗的时间
实现
OpenCV 4 中提供了对图像进行中值滤波操作的medianBlur()
函数
medianBlur(src, dst, ksize)
- src:待中值滤波的图像。如若滤波器尺寸较大,则数据类型只能是CV_8U
- dst:输出图像,与输入图像src具有相同的尺寸和数据类型
- ksize:滤波器尺寸,必须是大于1的奇数
实现代码:
// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;
int main()
{
Mat_<Vec3b> image = imread("/home/kslas/OpenCV/wood.jpg", -1);
// Apply Median Blur
Mat_<Vec3b> median_blurred;
medianBlur(image, median_blurred, (5,5));
imshow("Original", image);
imshow("Median Blurred", median_blurred);
waitKey();
destroyAllWindows();
return 0;
}
运行结果:
双边滤波(Bilateral Filtering)
简介
-
双边滤波本质上是对图像应用二维高斯模糊,同时还考虑相邻像素强度的变化以最小化边缘附近的模糊,可以实现在保留区域信息的基础上实现对噪声的去除、对局部边缘的平滑
-
双边滤波器是两个滤波器的结合,分别考虑颜色强度的变化以及与过滤像素的距离,使得滤波器对边缘附近的像素进行滤波时,距离边缘较远的像素值不会对边缘上的像素值影响太多,进而保留边缘的清晰性
实现
OpenCV 4 提供了对图像进行双边滤波操作的bilateralFilter()
函数
bilateralFilter(src, dst, d, sigmaColor, sigmaSpace)
- src:待进行双边滤波图像,类型必须为CV_8U、CV_32F、CV_64F三者之一,并且通道数必须为单通道或者三通道
- dst:双边滤波后的图像,尺寸、数据类型和通道数与输入图像相同
- d:滤波过程中每个像素邻域的直径,直径越大,滤波效果越明显
- sigmaColor:颜色空间滤波器的标准差值,一般尽可能大。该参数越大,表明该像素邻域内有越多的颜色被混合到一起,产生较大的半相等颜色区域
- sigmaSpace:空间坐标中滤波器的标准差值,一般尽可能小。参数值越大意味着只要它们的颜色足够接近,越远的像素都会相互影响
PS:当 d > 0 时,它指定邻域大小而不考虑 sigmaSpace。 否则,d与 sigmaSpace 成正比
实现代码:
// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;
int main()
{
Mat_<Vec3b> image = imread("/home/kslas/OpenCV/wood.jpg", -1);
// Apply bilateral filtering
Mat_<Vec3b> bilateral_filter;
bilateralFilter(image, bilateral_filter, 9, 75, 75);
imshow("Original", image);
imshow("Bilateral filtering", bilateral_filter);
waitKey(0);
destroyAllWindows();
return 0;
}
运行结果:
自定义滤波
简介
- 函数
cv::filter2D()
允许我们使用自己构造的卷积核对图像进行卷积
filter2D(src, dst, ddepth, kernel)
-
src:输入图像
-
dst:输出图像,与输入图像具有相同的尺寸和通道数
-
ddepth:输出图像的数据类型(深度),
-
根据输入图像的数据类型不同,拥有不同的取值范围,具体看下表
输入图像数据类型 输出图像可选数据类型 CV_8U -1 / CV_16S / CV_32F / CV_64F CV_16U / CV_16S -1 / CV_32F / CV_64F CV_12F -1 / CV_32F / CV_64F CV_64F -1 / CV_64F 当赋值为-1时,输出图像的数据类型自动选择
-
-
kernel:卷积核
PS:如果需要用不同的卷积对不同的通道进行卷积操作,就需要先使用spilt()
函数将图像多个通道分离之后单独对每一个通道求取卷积运算
实现
在下面的代码中,3x3 矩阵定义了一个锐化卷积核
// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;
int main()
{
Mat_<Vec3b> image = imread("/home/kslas/OpenCV/wood.jpg", -1);
// Apply sharpening using kernel
Mat_<Vec3b> sharp_img;
Mat_<double> kernel3 = (Mat_<double>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
filter2D(image, sharp_img, -1 , kernel3, Point(-1, -1), 0, BORDER_DEFAULT);
imshow("Original", image);
imshow("Sharpenned", sharp_img);
waitKey();
destroyAllWindows();
return 0;
}
运行结果: