图像滤波
对图像进行单个像素操作,主要是进行对比度和阈值处理
而图像滤波在像素邻域间进行,一来达到我们希望的效果,二来进一步进行图像特征提取
滤波分为空间域和频域滤波,空间域滤波又分线性、非线性滤波
常用的线性滤波有,均值滤波,高斯滤波;非线性滤波有中值滤波,双边滤波
线性滤波
均值模糊:blur()
void blur( InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT );
- src 源图像
- dst 输出图像
- ksize 卷积核
- anchor 锚点在核中心
- borderType 图像边界处理方式
卷积核如下图所示
高斯模糊:GaussianBlur()
void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT );
- src 源图像
- dst 目的图像
- ksize 高斯核,ksize.width与ksize.height可以不同,但必须为正的奇数.可以为0,通过simga计算得到
- sigmaX 高斯核在x方向的标准差
- sigmaY 高斯核在y方向的标准差
- borderType 边界像素处理方式
均值与高斯模糊代码:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int main() { 8 9 Mat srcImage = imread("D:/lena.png"); 10 if (!srcImage.data) { 11 cout << "could not load image" << endl; 12 return -1; 13 } 14 imshow("src Image", srcImage); 15 16 Mat bImage, gImage; 17 blur(srcImage, bImage, Size(3, 3)); 18 GaussianBlur(srcImage, gImage, Size(3, 3), 11, 11); 19 20 imshow("blur", bImage); 21 imshow("Gaussblur", bImage); 22 waitKey(0); 23 return 0; 24 }
效果图:
非线性滤波
统计排序滤波器是一种非线性滤波器,最知名的便是中值滤波。它将滤波器所包含的图像区域进行排序,选取中间值代替该点像素值,
其对椒盐噪声处理十分有效
中值滤波
void medianBlur( InputArray src, OutputArray dst, int ksize );
- src 源图像
- dst 目的图像
- ksize 孔径尺寸,必须为大于1的奇数
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 8 //加入椒盐噪声 9 void salt(Mat image, int n) 10 { 11 int i, j; 12 for (int k = 0; k<n; k++) 13 { 14 // rand()是随机数生成器 15 i = rand() % image.cols; 16 j = rand() % image.rows; 17 if (image.type() == CV_8UC1) 18 { // 灰度图像 19 if(rand()% 2 == 0) 20 image.at<uchar>(j, i) = 255; 21 else 22 image.at<uchar>(j, i) = 0; 23 } 24 else if (image.type() == CV_8UC3) 25 { // 彩色图像 26 if (rand()%2==0) { 27 image.at<cv::Vec3b>(j, i)[0] = 255; 28 image.at<cv::Vec3b>(j, i)[1] = 255; 29 image.at<cv::Vec3b>(j, i)[2] = 255; 30 } 31 else{ 32 image.at<cv::Vec3b>(j, i)[0] = 0; 33 image.at<cv::Vec3b>(j, i)[1] = 0; 34 image.at<cv::Vec3b>(j, i)[2] = 0; 35 } 36 } 37 } 38 } 39 40 int main() { 41 42 Mat srcImage = imread("D:/lena.png"); 43 if (!srcImage.data) { 44 cout << "could not load image" << endl; 45 return -1; 46 } 47 salt(srcImage, 1500); //加入椒盐噪声 48 imshow("src Image", srcImage); 49 50 Mat mImage; 51 medianBlur(srcImage, mImage, 3); //中值滤波 52 imshow("medianblur", mImage); 53 54 waitKey(0); 55 return 0; 56
效果图:
双边滤波
1.介绍 双边滤波(Bilateral Filtering)是一种简单,非迭代的保边去噪算法。
在最广泛的意义上“滤波”这一词,滤波图像在给定位置的值是输入图像在相同位置小邻域中的函数。
例如,高斯低通滤波(Gaussian low-pass fitering)计算像素邻域中得加权平均值,权重随着远离邻域中心减少。
虽然可以给出这种权重下降的正式和定量解释,但直觉是图像通常在空间上缓慢变化,
因此邻近像素可能具有相似的值,因此将它们平均在一起是合适的。
破坏这些邻近像素的噪声值与信号值相互关联较少,因此,当信号被保留时,噪声平均消失。
然而在边缘处,假设的缓慢空间变化失效了,因此会被线性低通滤波器模糊。
如何在平滑图像的同时,防止边缘被平均呢?下面介绍双边滤波的基本思路。
2.思路
双边滤波的基本思想是在传统空域滤波中引入值域滤波。两个像素可以彼此接近,即占据附近的空间位置,或者它们可以彼此相似,即具有邻近的值。
考虑应用于图像的平移不变低通域滤波器:
归一化常数
类似的定义值滤波器:
在这种情况下归一化常数:
解决方案是结合空域和值滤波,组合滤波可以描述如下:
归一化常数是,
结合空域与值域滤波被定义为双边滤波。在光滑的区域,邻域中像素的值差异不大,双边滤波的效果与标准空间滤波等同,
平均的消除噪声引起的像素值之间的小的、弱相关的差异。
在边缘处,滤波器用其附近的明亮像素的平均值代替中心处的明亮像素,并且基本上忽略了暗像素,
反之,当滤波器以暗像素为中心时,则忽略了明亮像素。
至此,由于滤波器的空域成分,边界得以保存;由于滤波器的值域成分,清晰的边缘也得以保存
void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT );
- src 单通道,浮点类型,源图像
- dst 输出图像,与src类型一致
- d 用于滤波的每个像素邻域的直径。如果它是非正的,
它是从sigmaSpace计算出来的
- sigmaColor 较大的参数值意味着像素邻域内的较远颜色(参见sigmaSpace)将混合在一起
- sigmaSpace 坐标空间中的sigmaSpace滤波器。参数值越大意味着越远处的像素(若像素足够接近)会影响该点像素
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int main() { 8 Mat src, dst; 9 src = imread("D:/kitten-orig.png"); 10 if (src.empty()) { 11 cout << "could not load image..." << endl; 12 return -1; 13 } 14 bilateralFilter(src, dst, 9, 75, 75); 15 namedWindow("input", CV_WINDOW_AUTOSIZE); 16 imshow("input", src); 17 namedWindow("output", CV_WINDOW_AUTOSIZE); 18 imshow("output", dst); 19 imwrite("kitten-outp.png", dst); 20 waitKey(0); 21 }
效果对比: