假设有6x6的图像像素点矩阵(灰色) ,黄色3x3是卷积算子
卷积过程:6x6上面有个3x3的窗口,这个3x3的窗口从左向右,从上向下移动
黄色的卷积算子乘以图像对应的像素点后,将得到的像素点值加在一起,取平均值赋给中心红色像素,作为卷积处理后的新的像素值
1. 归一化盒子滤波(均值滤波)
@param src input image; it can have any number of channels, which are processed independently, but
the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize blurring kernel size.
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel
center.
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes
@sa boxFilter, bilateralFilter, GaussianBlur, medianBlur
void blur( InputArray src, OutputArray dst,Size ksize, Point anchor = Point(-1,-1),int borderType = BORDER_DEFAULT );
矩阵卷积运算的具体过程
假设有一个卷积核h,就一般为33的矩阵:
有一个待处理矩阵x:
hx的计算过程分为三步
第一步,将卷积核翻转180°,也就是成为了
第二步,将卷积核h的中心对准x的第一个元素,然后对应元素相乘后相加,没有元素的地方补0。
这样结果Y中的第一个元素值Y11=10+20+10+00+01+02±10±25±1*6=-16
第三步每个元素都像这样计算出来就可以得到一个输出矩阵,就是卷积结果
……………………
像这样计算,其他过程略了。
最后结果
均值滤波参考代码
#include
#include
using namespace std;
using namespace cv;
int main (int argc,char **argv)
{
Mat src = imread("/home/shining/工作/Opencv-test/picture/girl.jpg",1);
if(src.empty())
{
cout << "Could not load image.."<
2. 高斯滤波
高斯滤波:正态分布
其中Size(x, y), x, y 必须是正数而且是奇数
@param src input image; the image can have any number of channels, which are processed
independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be
positive and odd. Or, they can be zero's and then they are computed from sigma.
@param sigmaX Gaussian kernel standard deviation in X direction.
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
respectively (see #getGaussianKernel for details); to fully control the result regardless of
possible future modifications of all this semantics, it is recommended to specify all of ksize,
sigmaX, and sigmaY.
@param borderType pixel extrapolation method, see #BorderTypes
void GaussianBlur( InputArray src, OutputArray dst, Size ksize,double sigmaX, double sigmaY = 0,int borderType = BORDER_DEFAULT );
高斯滤波参考代码
#include
#include
using namespace std;
using namespace cv;
int main (int argc,char **argv)
{
Mat src = imread("/home/shining/工作/Opencv-test/picture/girl.jpg",1);
if(src.empty())
{
cout << "Could not load image.."<
说明1
模糊原理: 同样的卷积因子,均值模糊会比高斯模糊更模糊些。 不管对于哪种模糊,卷积核(比如3*3)的大小最好是奇数
说明2
在模糊处理方面,filter2D() 也可以自己定义卷积核;
参考代码:
#include
#include
using namespace cv;
int main(int argc,char** argv){
Mat src=imread("E:/Experiment/OpenCV/Pictures/test.jpg");
if(src.empty()){
printf("Could not load Image ...");
return -1;
}
char input_windows[]="Input Image";
char blur_windows[]="blur Image";
char gblur_windows[]="GBlur Image";
namedWindow(input_windows,CV_WINDOW_AUTOSIZE);
namedWindow(blur_windows,CV_WINDOW_AUTOSIZE);
namedWindow(gblur_windows,CV_WINDOW_AUTOSIZE);
imshow(input_windows,src);
//模糊处理
Mat blur_dst,gblur_dst;
//均值模糊
blur(src, blur_dst, Size(5, 5), Point(-1, -1));
imshow(blur_windows,blur_dst);
//高斯模糊
GaussianBlur(src, gblur_dst, Size(5, 5), 11, 11);
imshow(gblur_windows,gblur_dst);
waitKey(0);
return 0;
}
模糊是基本的图像处理方法。
在介绍中值滤波和双边滤波之前先来介绍两种常见的噪声:
椒盐噪声
椒盐噪声是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。椒盐噪声分为两种即胡椒噪声和盐噪声,胡椒噪声是黑色的,属于低灰度噪声,盐噪声是白色的,属于高灰度噪声,一般两种噪声同时出现,呈现在图像上就是黑白杂点。去除椒盐噪声最常用的算法是中值滤波。
高斯噪声
高斯噪声是一种随机噪声,其幅度的统计规律服从高斯分布(正态分布),去高斯噪声最常用的算法是高斯滤波。
这些噪声出现在图片上某一点时都是比较突兀的,如出现椒盐噪声时,图片中突然某一点突然变成0或255,一般与噪声周围的灰度值有较大的差值,所以图像在去噪时一般都是用周围像素的灰度值经过一定的算子来改变这点像素上较为突兀的灰度值,但缺陷是对原来正常的像素点的灰度值也会产生影响使图片变得模糊;
在图像处理时,灰度图片一般会被视为一个矩阵,而图像上的每一像素所代表的灰度值被视为矩阵中相应位置中的元素,如一幅100×100像素的黑色灰度图片就可以视为100×100的一个矩阵,矩阵中的每一个元素都为0;
对图像进行处理也可以视为对这个矩阵进行处理。
在锐化和模糊时,会用到一些模板,这些模板是一个小如3×3,5×5的矩阵,用来与原图像进行处理产生新的图像,如在均值滤波时常用的模板
用上图所示的模板对图片的每一像素和其相邻像素组成的邻域进行卷积处理卷积的结果进行归一处理,结果为这一区域灰度值的平均值,用灰度值的平均值替代这一点像素的原灰度值。
均值滤波计算速度快,但会使图像变得较为模糊。
利用均值滤波处理后,椒盐噪声被处理成了小的气泡,与此同时图像开始变得模糊,均值滤波不适合椒盐噪声
void medianBlur( InputArray src, OutputArray dst, int ksize );
#include
#include
using namespace std;
using namespace cv;
int main (int argc,char **argv)
{
Mat src = imread("/home/shining/工作/Opencv-test/picture/girl_ZY.jpg",1);
if(src.empty())
{
cout << "Could not load image.."<
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为33,55区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。
均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),作为处理后图像在该点上的灰度g(x,y),即g(x,y)=1/m ∑f(x,y) m为该模板中包含当前像素在内的像素总个数。
void bilateralFilter( InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace,int borderType = BORDER_DEFAULT );
双边模糊 bilateralFilter(src, dest, d=15, 150, 3);
15 –计算的半径,半径之内的像数都会被纳入计算,如果提供-1 则根据sigma space参数取值
150 – sigma color 决定多少差值之内的像素会被计算
3 – sigma space 如果d的值大于0则声明无效,否则根据它来计算d值
中值模糊的ksize大小必须是大于1而且必须是奇数。
常说的双边滤波就是指高斯双边滤波(用于美颜)。两像素差值太大的不予考虑,像素差值有一个阈值范围,在这个范围的才考虑,其他原样输出,这个叫双边滤波。
在双边滤波的基础加上高斯权重,就叫高斯双边滤波。
均值模糊无法克服边缘像素信息丢失缺陷。原因是均值滤波是基于平均权重 权重都一样
高斯模糊部分克服了该缺陷,但是无法完全避免,因为没有考虑像素值的不同 高斯滤波考虑到了空间位置不一样,权重就不一样,越靠近中心权重越大
上面两种滤波所有的像素点都进行处理
高斯双边模糊 – 是边缘保留的滤波方法,避免了边缘信息丢失,保留了图像轮廓不变 考虑到了像素值的问题,只有像素值在阈值范围内,才进行处理
空域核 空间上考虑,每个点的权重不一样
值域核 像素值,像素值在阈值范围内
#include
#include
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
Mat src = imread("/home/shining/工作/Opencv-test/picture/girl_ZY.jpg",IMREAD_COLOR);
if(src.empty())
{
cout <<"Could not load image..."<(3,3) <<0,-1,0,-1,5,-1,0,-1,0);
filter2D(image5,image8,image5.depth(),kernel,Point(-1,-1));//调用OpenCV函数进行掩膜操作,src.depth表示位图深度,有32、24、8等,如果不知道也可以传-1,表示跟输入图像一样
imshow("outputlast",image8);
waitKey(0);
return 0;
}
推荐阅读: https://blog.csdn.net/qq_25819827/article/details/52050647