模糊图像(一)
模糊原理
(1)归一化盒子滤波(均值滤波):
(2)高斯滤波:
相关API
均值模糊:blur(Mat src,Mat dst,Size(xradius,yradius),Point(-1,-1));
高斯模糊:GaussianBlur(Mat src,Mat dst,Size(x,y),sigmax,sigmay);
其中,Size(x,y),x和y必须是正数而且是奇数。
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
int main(int argc, char** argv)
{
Mat src, dst;
src = imread("D:/studytest/lena.jpg");
if (src.empty())
{
printf("could not load image....\n");
return -1;
}
char input_title[] = "input image";
char output_title[] = "blur image";
namedWindow(input_title, CV_WINDOW_AUTOSIZE);
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(input_title, src);
blur(src, dst, Size(15, 15), Point(-1, -1));// Point(-1,-1)表示中心在模板正中心
imshow(output_title,dst);
Mat gblur;
GaussianBlur(src, gblur, Size(5, 5), 11, 11);
imshow("gaussian blur", gblur);
waitKey(0);
return 0;
}
模糊图像(二)
模糊原理
(1)中值滤波:
统计排序滤波器,中值对椒盐噪声有很好的抑制作用。
上图,用中值124替换掉绿色框正中间的150;
(2)双边滤波:
均值模糊无法克服边缘像素信息丢失缺陷。原因是均值滤波是基于平均权重。
高斯滤波部分克服了该缺陷,但是无法完全避免,因为没有考虑像素值的不同。
高斯双边模糊是边缘保留的滤波方法,避免了边缘信息丢失,保留了图像轮廓不变。
相关API
中值模糊medianBlur(Mat src,Mat dest,ksize);
ksize大小必须大于1而且必须是奇数。
双边模糊bilateralFilter(src,dest,d=15,150,3);
15-计算的半径,半径之内的像素都会被纳入计算,如果d=-1则根据sigma space参数取值
150-sigma color决定多少差值之内的像素会被计算
3-sigma space如果d的值大于0则声明无效,否则根据它来计算d的值
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src, dst1,dst2,dst3;
src = imread("D:/studytest/lenanoise.jpg");
if (!src.data)
{
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);//原图显示
imshow("input image", src);
medianBlur(src, dst1, 3);//中值模糊
namedWindow("median Filter Result", CV_WINDOW_AUTOSIZE);
imshow("median Filter Result", dst1);
bilateralFilter(src, dst2, 15, 150, 3);//双边模糊
namedWindow("bilateral Filter Result", CV_WINDOW_AUTOSIZE);
imshow("bilateral Filter Result", dst2);
GaussianBlur(src, dst3, Size(15,15), 3, 3);//高斯模糊
namedWindow("GaussianBlur Result", CV_WINDOW_AUTOSIZE);
imshow("GaussianBlur Result", dst3);
Mat resultImage;//对双边模糊后的图像进行对比度提高
Mat kernel = (Mat_<int>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(dst2, resultImage, -1, kernel, Point(-1, -1), 0);//filter2D官方描述为:Convolves an image with kernel即利用内核实现对图像的卷积运算
imshow("Final Result", resultImage);
waitKey(0);
return 0;
}
结果如下图所示:
(三)边缘处理
边缘卷积问题
如下图所示,图像卷积的时候边界像素无法被卷积操作,因为边缘像素没有完全和kernel重叠,所以当3×3滤波时,有一个像素的边缘没有被处理,5×5滤波时,有2个像素的边缘没有被处理,这时候我们就需要对边缘进行扩充处理。
边缘处理
上面几种介绍的模糊图像的方法,默认使用BORDER_DEFAULT。在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3×3在四周各填充1个像素的边缘,这样就确保图像的边缘被处理,在卷积处理之后再去掉这些边缘。openCV中默认的处理方法是:BORDER_DEFAULT,此外常用的还有如下几种方法:
BORDER_CONSTANT—填充边缘用指定像素值。
BORDER_REPLICATE—填充边缘像素用已知的边缘像素值。
BORDER_WRAP—用另外一边的像素来补偿填充。
图像添加边缘API
copyMakeBorder(Mat src,Mat dst,int top,int bottom,int left,int right,int borderType,Scalar value)
src:输入图像
dst:添加边缘后的图像
top:顶部边缘长度,一般上下左右都取相同值
bottom:底部边缘长度
left:左侧边缘长度
right:右侧边缘长度
borderType:边缘类型
value:填充的已知边缘像素值
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src, dst;
src = imread("D:/studytest/lena.jpg");
if (src.empty())
{
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
namedWindow("output image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
int top =(int)(0.05*src.rows);
int bottom =(int)(0.05*src.rows);
int left= (int)(0.05*src.cols);
int right = (int)(0.05*src.cols);
RNG rng(12345);
int borderType = BORDER_DEFAULT;
int c = 0;
while (true)
{
c = waitKey(500);
if ((char)c == 27) //ESC退出
break;
if ((char)c == 'r')
borderType = BORDER_REPLICATE;
else if ((char)c == 'w')
borderType = BORDER_WRAP;
else if ((char)c == 'c')
borderType = BORDER_CONSTANT;
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
copyMakeBorder(src, dst, top, bottom, left, right, borderType, color);
imshow("output image", dst);
}
imshow("output image", dst);
waitKey(0);
return 0;
}
borderType = BORDER_DEFAULT:
borderType = BORDER_REPLICATE:
borderType=BORDER_CONSTANT:
borderType = BORDER_WRAP: