最近交了数图作业,mark一下。
σ为z的标准差,z为均值,用E。
方法由Marsaglia和Bray在1964年提出,C++版本如下: mu是均值,sigma是方差,X服从N(0,1)分布
double generateGaussianNoise(double mu, double sigma)
{
static double V1, V2, S;
static int phase = 0;
double X;
double U1,U2;
if ( phase == 0 ) {
do {
U1 = (double)rand() / RAND_MAX;
U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else{
X = V2 * sqrt(-2 * log(S) / S);
}
phase = 1 - phase;
return mu+sigma*X;
}
高斯噪声为加性噪声,在原图的基础上加上噪声即为加噪后的图象。
代码如下:
void AddNoise(Mat img,double mu, double sigma,int k){
Mat outImage;
outImage.create(img.rows,img.cols,img.type());
for(int x=0;xfor(int y=0;ydouble temp = img.at(x, y)
+k*generateGaussianNoise(mu,sigma);
if(temp>PixcelMax)
temp=PixcelMax;
else if(temp(x, y) = temp;
}
}
Filter(outImage,Filter::NXBJZ,3,3,1);
imshow("Output", outImage);
cvWaitKey(0);
}
如图,k为高斯噪声的系数,系数越大,高斯噪声越强。
噪声服从高斯分布,所以方差越大,数据越分散,噪声也就越多。
均值决定着整个图像的明亮程度,均值大于0,表示图像加上一个使自己变亮的噪声,小 于0,表示图像加上一个使自己变暗的噪声。
椒盐噪声是根据图像的信噪比,随机生成一些图像内的像素位置,并随机对这些像素点赋值为0或255.
代码如下:
void AddNoise(Mat img,double SNR ){
Mat outImage;
outImage.create(img.rows,img.cols,img.type());
int SP = img.rows*img.cols;
int NP = SP*(1-SNR);
outImage = img.clone();
for(int i=0; iint x = (int)(rand()*1.0/RAND_MAX* (double)img.rows);
int y = (int)(rand()*1.0/RAND_MAX* (double)img.cols);
int r = rand()%2;
if(r){
outImage.at(x, y)=0;
}
else{
outImage.at(x, y)=255;
}
}
Filter(outImage,Filter::NXBJZ,3,3,1);
imshow("Output", outImage);
cvWaitKey(0);
}
其中,SNR为信噪比,利用C++中的rand() 作为随机函数。
信噪比越小,噪声越多,信噪比为1时,图像不含噪声。 0为胡椒噪声,255为盐粒噪声
Sx,y为以(x,y)为中心,长为m宽为n的矩形范围。
总结:
只能在噪声较少的情况下去除些许噪声,并且只是平滑了图像的局部变化,令图像变得模
糊。
Sx,y为以(x,y)为中心,长为m宽为n的矩形范围。
总结:
处理高斯噪声时,噪声较少时,效果与算术均值滤波器基本一致。但是噪声较多时,
会对灰度值较小的噪声进行放大,导致图像出现许多黑点,使图像变暗。
处理椒盐噪声时,会对胡椒噪声放大,导致图像出现许多黑点,而对盐粒噪声有较好
的滤除作用。
总结:
与几何均值滤波器有相似的效果,处理高斯噪声时,会对灰度值较小的噪声进行放
大,导致图像出现许多黑点,使图像变暗。
处理椒盐噪声时,会对胡椒噪声放大,导致图像出现许多黑点,无法处理胡椒噪声,
而对盐粒噪声有较好的滤除作用。
总结:
Q为正时,会对灰度值较大的噪声进行放大,Q为负时,会对灰度值较小的噪声进行 放大。
处理椒盐噪声时,Q为正,对胡椒噪声有较好的滤除作用,Q为负,对盐粒噪声有较 好的滤除作用。
代码如下:
void Filter(Mat img,Filter f,int m,int n,int Q = 0){
Mat outImage;
outImage.create(img.rows,img.cols,img.type());
int h = m/2,w=n/2;
for(int x=0;xfor(int y=0;yint cnt = 0;
if(f== Filter::SSJZ){
long double sum = 0;
for(int i=x-h;i<=x+h;i++){
for(int j=y-w;j<=y+w;j++){
if(i<0||i>=img.rows||j<0||j>=img.cols)continue;
cnt++;
sum+=img.at(i, j);
}
}
outImage.at(x, y)=sum/cnt;
}
else if(f== Filter::JHJZ){
long double sum = 1;
for(int i=x-h;i<=x+h;i++){
for(int j=y-w;j<=y+w;j++){
if(i<0||i>=img.rows||j<0||j>=img.cols)continue;
cnt++;
sum*=img.at(i, j);
}
}
outImage.at(x, y)=pow(sum,1.0/cnt);
}
else if(f== Filter::XBJZ){
long double sum = 0;
for(int i=x-h;i<=x+h;i++){
for(int j=y-w;j<=y+w;j++){
if(i<0||i>=img.rows||j<0||j>=img.cols)continue;
cnt++;
sum+=1.0/img.at(i, j);
}
}
outImage.at(x, y)=cnt/sum;
}
else if(f== Filter::NXBJZ){
long double sum1 = 0,sum2 = 0;
for(int i=x-h;i<=x+h;i++){
for(int j=y-w;j<=y+w;j++){
if(i<0||i>=img.rows||j<0||j>=img.cols)continue;
cnt++;
sum1+=pow(img.at(i, j),Q);
sum2+=pow(img.at(i, j),Q+1);
}
}
outImage.at(x, y)=sum2/sum1;
}
}
}
imshow("Output", outImage);
imwrite("/Users/camellia/desktop/gaussnoise_NXBJZ.jpg", outImage);
cvWaitKey(0);
}
2017.7.31更新——
补充
四种滤波器
SSJZ——算术均值滤波器
JHJZ——几何均值滤波器
XBJZ——谐波均值滤波器
NXBJZ——逆谐波均值滤波器
enum Filter{
SSJZ,JHJZ,XBJZ,NXBJZ
};
int main()
{
Mat image;
image = imread("/Users/camellia/desktop/lena.jpg",0);// 测试图片路径
if ( !image.data )
{
printf("No image data \n");
return -1;
}
namedWindow("Display Image", WINDOW_AUTOSIZE );
imshow("Display Image", image);
imwrite("/Users/camellia/desktop/origin.jpg", image);
waitKey(0);
// AddNoise(image,0,1,64);
AddNoise(image,0.98);
// Filter(image,SSJZ,5,5);
// Filter(image,JHJZ,5,5);
// Filter(image,XBJZ,5,5);
// Filter(image,NXBJZ,5,5);
return 0;
}