模糊是基本的图像处理方法。
在介绍这两种方法之前先来介绍两种常见的噪声:
椒盐噪声
椒盐噪声是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。椒盐噪声分为两种即胡椒噪声和盐噪声,胡椒噪声是黑色的,属于低灰度噪声,盐噪声是白色的,属于高灰度噪声,一般两种噪声同时出现,呈现在图像上就是黑白杂点。去除椒盐噪声最常用的算法是中值滤波。
高斯噪声
高斯噪声是一种随机噪声,其幅度的统计规律服从高斯分布(正态分布),去高斯噪声最常用的算法是高斯滤波。
而这些噪声出现在图片上某一点时都是比较突兀的,如出现椒盐噪声时,图片中突然某一点的会突然变成0或255,一般与噪声周围的灰度值有较大的差值,所以图像在去噪时一般都是用周围像素的灰度值经过一定的算子来改变这点像素上较为突兀的灰度值,但缺陷是对原来正常的像素点的灰度值也会产生影响使图片变得;
在图像处理时,灰度图片一般会被视为一个矩阵,而图像上的每一像素所代表的灰度值被视为矩阵中相应位置中的元素,如一幅100×100像素的黑色灰度图片就可以视为100×100的一个矩阵,矩阵中的每一个元素都为0;对图像进行处理也可以视为对这个矩阵进行处理。
在锐化和模糊时,会用到一些模板,这些模板是一个小如3×3,5×5的矩阵,用来与原图像进行处理产生新的图像,如在均值滤波时常用的模板
均值滤波:
用如的模板对图片的每一像素和其相邻像素组成的领域进行进行卷积处理,卷积的结果进行归一处理,结果为这一区域灰度值的平均值,用灰度值的平均值替代这一点像素的原灰度值。 均值滤波计算速度快,但会使图像变得较为模糊。因为手机无法像单反改变光圈来改变景深情况下(HTC的M8有专门的景深摄像头除外),其他的都是利用算法对背景进行模糊处理。
公式
g(x,y)=19∗∑f⊂sf(x,y)
其中s表示处理像素点与周围像素形成的一块区域;
//均值滤波
uchar junzhi(uchar* fx,int cols)
{
int model[3][3] = { { 1, 1, 1 },
{ 1, 1, 1 },
{ 1, 1, 1 }};
uchar dir;
dir =( *(fx - cols - 1)*model[0][0] + *(fx - cols)*model[0][1] + *(fx -cols + 1)*model[0][2] +
*(fx - 1)*model[1][0] + *(fx)*model[1][1] + *(fx + 1)*model[1][2] +
*(fx + cols + 1)*model[2][0] + *(fx + cols)*model[2][1] + *(fx + cols+ 1)*model[2][2])/9;
return dir;
}
处理后效果:
中值滤波:
用模板进行处理,并用区域中的中值替代这一点的像素值:
模板:
公式:
g(x,y)=midf∈sf(x,y)
其中S是像素所在的领域;
实现代码:
//中值滤波
uchar zhongzhi(uchar *fx, int cols)
{
uchar model[9];
uchar temp;
model[0] = *(fx - cols - 1);
model[1] = *(fx - cols);
model[2] = *(fx - cols + 1);
model[3] = *(fx - 1);
model[4] = *(fx);
model[5] = *(fx + 1);
model[6] = *(fx + cols - 1);
model[7] = *(fx + cols);
model[8] = *(fx + cols + 1);
for (int i = 8; i >-1; i--)
{
for (int j = 0; j < i; j++)
{
if (model[i] < model[j])
{
temp = model[i];
model[i] = model[j];
model[j] = temp;
}
}
}
return model[4];
}
处理效果:
明显右边白框中黑点减少了;
高斯滤波:
主要原理是根据高斯函数获得相应的滤波模板矩阵,再用这个矩阵去处理图像,对高斯噪声有较好的模糊作用;
根据二维高斯公式:
G(x,y)=12πσe−(x2+y2)2σ2
在根据每一点与中心点的位置可以得到其权重矩阵
由于正态方差为1,
σ
=1
根据公式进行计算后得到的矩阵再进行归一化处理后可以得到模板矩阵:
代码:
//gaoshi
uchar gauss(uchar* fx, int cols)
{
int model[3][3] = { { 1, 2, 1 },
{ 2, 4, 2 },
{ 1, 2, 1 } };
uchar dir;
dir = (*(fx - cols - 1)*model[0][0] + *(fx - cols)*model[0][1] + *(fx - cols + 1)*model[0][2] +
*(fx - 1)*model[1][0] + *(fx)*model[1][1] + *(fx + 1)*model[1][2] +
*(fx + cols + 1)*model[2][0] + *(fx + cols)*model[2][1] + *(fx + cols + 1)*model[2][2]) / 16;
return dir;
}
与opencv中的高斯滤波效果比较:
main函数:
#include<opencv2\opencv.hpp>
#include<stdio.h>
#include<cv.h>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\core\core.hpp>
#include<iostream>
#include<Windows.h>
using namespace cv;
using namespace std;
void filtering(Mat src, Mat dir)
{
int mn=0;
uchar* psrc = (uchar*)src.data;
uchar* pdir = (uchar*)dir.data;
psrc = psrc + src.cols+1;
pdir = pdir + src.cols+ 1;
for (int i = 1; i < src.rows-1; i++)
{
for (int j = 1; j < src.cols - 1; j++)
{
*(pdir) =junzhi(psrc, src.cols);//自己要用的滤波
psrc++;
pdir++;
}
}
}
void main()
{
Mat src = imread("5.tif",0);
imshow("src", src);
Mat dir(src.rows, src.cols, CV_8UC1);
filtering(src, dir);
imshow("dir", dir);
//GaussianBlur(src, dir,Size(3,3), 0, 0);
//imshow("gauss", dir);
waitKey();
}
由于笔者能力有限,其中会有错误,欢迎提出