算术均值检波与中值滤波去噪
我们晓得在图象生成和传输的过程中,很容易形成噪音干扰。噪声虽然分为好多类型,分为泊松噪音、椒盐噪音等。这我们就不一一赘言了,我们主要介绍一下怎样通过算术均值混频和中值检波对通常的酱汁噪音进行平滑去噪。
首先我们须要明白算术均值混频去噪以及中值滤波去噪的基本原理,而后我们能够通过代码实现,以期达成最终目的。
一、 算术均值混频去噪
首先我们应该晓得,图像的各个象素之间具有极大的相关性,而噪音的形成就标志着噪音这一点的象素与它周围的象素“格格不入”。因此我们可以先假定一个九宫格模型,把整个图象借助九宫格遍历一遍。并对每一个RGB份量进行相同的九宫格平均操作3*3中值滤波器模板,即把每一个象素都作为九宫格的核心,然后分别将九宫格内的象素相乘最终平均一下,重新形参给当前遍历到的象素值。具体流程如下图:
这么一看是不是认为这个算术均值混频很简单呀?下面是代码实现:
//对图像进行算数均值滤波
//算法思想:对一组像素点取平均值赋值给中心点
public static BufferedImage average(BufferedImage leftImage) {
int width = leftImage.getWidth();
int height = leftImage.getHeight();
int srcRGBs[] = leftImage.getRGB(0, 0, width, height, null, 0, width);
//BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int rgb[]=new int[3];
int rs[][]=new int[width][ height]; //
int gs[][]=new int[width][ height];
int bs[][]=new int[width][ height];
for(int j=0; j<height; j++) {
for (int i = 0; i < width; i++) {
ImageUtil.decodeColor(srcRGBs[j*width+i],rgb); //rgb[0]=R,rgb[1]=G,rgb[2]=B
rs[i][j]=rgb[0]; //Rֵ
gs[i][j]=rgb[1]; //Gֵ
bs[i][j]=rgb[2]; //bֵ
}
}
BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int r=0,g=0,b=0;
for (int j = 0; j < height; j++) {
for(int i=0; i<width; i++) {
try {
ImageUtil.decodeColor(srcRGBs[j*width+i],rgb); //rgb[0]=R,rgb[1]=G,rgb[2]=B
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(i);
}
if (j>=1&&i>=1&&j<height-1&&i<width-1){
rgb[0]=(int)((rs[i-1][j-1]+rs[i][j-1]+rs[i+1][j-1]+
rs[i-1][j]+rs[i][j]+rs[i+1][j]+
rs[i-1][j+1]+rs[i][j+1]+rs[i+1][j+1])/9);
rgb[1]=(int)((gs[i-1][j-1]+gs[i][j-1]+gs[i+1][j-1]+
gs[i-1][j]+gs[i][j]+gs[i+1][j]+
gs[i-1][j+1]+gs[i][j+1]+gs[i+1][j+1])/9);
rgb[2]=(int)((bs[i-1][j-1]+bs[i][j-1]+bs[i+1][j-1]+
bs[i-1][j]+bs[i][j]+bs[i+1][j]+
bs[i-1][j+1]+bs[i][j+1]+bs[i+1][j+1])/9);
}else {
rgb[0]=rs[i][j];
rgb[1]=gs[i][j];
rgb[2]=bs[i][j];
}
destImage.setRGB(i,j, ImageUtil.encodeColor(rgb));
}
}
return destImage;
}
下面是疗效展示:
值得注意的是3*3中值滤波器模板,算术均值混频对于边沿一圈像素点的处理有些玩味道,他有自身的局限性,目前我尚不知道怎么解决,有解决了的,还请下边评论告知!但是中值滤波有办法解决,并且呈现疗效更好,下面我们看中值混频怎样去噪!
二、 中值滤波去噪
其实类似于算术均值混频,我们也是要去一个九宫格模型,然后对每位象素值进行九宫格处理,但是不同的是我们此次把将整个九宫格平均一下给当前象素值了,我们将九宫格内的所有象素进行排序,取排在中间的象素值赋给当前待处理的象素值。
这是有一定的内在原理的,一个就是象素的相关性,还有一个就是酱汁噪音的噪音点要么是0要么是255,因此若当前我们要处理的刚好是噪音点,那么赋给该噪音点的不可能会是它本来的象素值,而更可能是周围的正常的象素值。
下面是代码实现过程:
//中值滤波
//算法思想:将一组像素值排序,将中间大小的像素值赋值给目标点
public static BufferedImage getMid(BufferedImage leftImage) {
int width = leftImage.getWidth();
int height = leftImage.getHeight();
int srcRGBs[] = leftImage.getRGB(0, 0, width, height, null, 0, width);
int rgb[]=new int[3];
int rs[][]=new int[width][ height]; //
int gs[][]=new int[width][ height];
int bs[][]=new int[width][ height];
for(int j=0; j<height; j++) {
for (int i = 0; i < width; i++) {
ImageUtil.decodeColor(srcRGBs[j*width+i],rgb); //rgb[0]=R,rgb[1]=G,rgb[2]=B
rs[i][j]=rgb[0]; //Rֵ
gs[i][j]=rgb[1]; //Gֵ
bs[i][j]=rgb[2]; //bֵ
}
}
BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int rgbs0[]=new int[9];
int rgbs1[]=new int[9];
int rgbs2[]=new int[9];
for (int j = 0; j < height; j++) {
for(int i=0; i<width; i++) {
try {
ImageUtil.decodeColor(srcRGBs[j*width+i],rgb); //rgb[0]=R,rgb[1]=G,rgb[2]=B
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(i);
}
int x=i,y=j;
x=x<1?1:x;
y=y<1?1:y;
x=x>=width-1?width-2:x;
y=y>=height-1?height-2:y;
int sum0=0;
for(int k=-1;k<2;k++){
for(int l=-1;l<2;l++){
rgbs0[sum0]=rs[x+k][y+l];
sum0++;
}
}
int sum1=0;
for(int k=-1;k<2;k++){
for(int l=-1;l<2;l++){
rgbs1[sum1]=gs[x+k][y+l];
sum1++;
}
}
int sum2=0;
for(int k=-1;k<2;k++){
for(int l=-1;l<2;l++){
rgbs2[sum2]=bs[x+k][y+l];
sum2++;
}
}
sort(rgbs0);
sort(rgbs1);
sort(rgbs2);
rgb[0]=rgbs0[4];
rgb[1]=rgbs1[4];
rgb[2]=rgbs2[4];
destImage.setRGB(i,j, ImageUtil.encodeColor(rgb));
}
}
return destImage;
}
这里有个处理边沿问题的小技巧,我假原图象周围有一圈的红色象素点,这样既不会影响最终的值,也能处理好真正边沿的象素。
下面是疗效展示:
至此,我们借助两个混频消除噪音的方式和简单原理就介绍完了,总体来说还是比较简单的,但也希望能帮助你们一点点。
总代码包下载: