矢量中值滤波对彩色图像进行去噪
一、对彩色图像进行中值滤波去噪的特点
之前我们其实说过对灰度图像进行中值滤波去噪的操作,但是对彩色图像利用中值滤波去噪的情况又有所不同,其主要原因是灰度图像的rgb分量均相同,而彩色图像的rgb分量绝大多数是互不相同的。这样的一个差别就导致了我们对一组向量的rgb分量进行排序是应当如何选择中值的问题。
二、选择中值的三种方式
一般来说对彩色图像进行rgb排序选择中值的方式有三种:
1) 边缘排序:对rgb三个分量分别排序,最终选择的像素值为rgb三个分量中分别排在中间的那个分量值组成的像素值;
2) 条件排序:选择rgb分量中的一个分量进行排序(如果选择的该分量均相同,则考虑第二个分量),根据该排序结果,选择对应的像素值作为中值;
3) 简化/合计排序:将所有的像素值用给定的简化函数组合转化成标量再进行排序;
三、 三种方式性能分析
上述第一种方式,虽然简单易懂,但是他很可能会因为三个分量的分别排序与组合产生了该组像素值中所没有的新像素值,这种情况其实我们应当是需要避免的,以防出现失真现象。
上述第二种方法,虽然克服了第一种方法可能会产生新像素值这种缺点,但是该方法总体来说更加片面,往往选择的分量不合适,最后出来的结果可能就不理想。
上述第三种方法较前两种方法来说又更为合理,但是这个简化函数我们需要进行合理选择,这里我们选择距离函数作为简化函数,具体如下:
ri={[f-fm]T[f-fm]} 1/2其中, fm=(f1+f2+f3+… +fn)/n
例:给定一组N=7个彩色像素:f1=[7,1,1], f2=[4,2,1], f3=[3,4,2], f4=[6,2,6], f5=[5,3,5], f6=[3,6,6], f7=[7,3,7]
简化/合计排序:用距离函数作简化函数,即:ri={[f-fm]T[f-fm]}1/2
其中, fm=(f1+f2+f3+f4+f5+f6+f7)/7=[5,3,4]T
计算:r1=[(7-5)2+(1-3)2+(1-4)2]1/2=4.12
r2=3.61, r3=3, r4=2.45, r5=1, r6=4.12, r7=3.61
r5最小,则,中值矢量为:[5,3,5]
由此,我们通过距离函数作为简化函数的步骤已经完善了,接下来就是通过代码去实现。
四、 代码实现
//矢量中值滤波
public static BufferedImage VectorMid(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+2][ height+2]; //
int gs[][]=new int[width+2][ height+2];
int bs[][]=new int[width+2][ height+2];
for(int j=1; j<height+1; j++) {
for (int i = 1; i < width+1; i++) {
ImageUtil.decodeColor(srcRGBs[(j-1)*width+i-1],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 px[][]=new int[5][3];
double dpx[]=new double[5]; //用来记录各个像素点距离中值的距离
int fm[]=new int[3];
for (int j = 1; j < height+1; j++) {
for(int i=1; i<width+1; i++) {
ImageUtil.decodeColor(srcRGBs[(j-1)*width+i-1],rgb); //rgb[0]=R,rgb[1]=G,rgb[2]=B
px[0][0]=rs[i][j-1];//存储该像素点的红色
px[0][1]=gs[i][j-1];
px[0][2]=bs[i][j-1];
px[1][0]=rs[i-1][j];//存储该像素点的红色
px[1][1]=gs[i-1][j];
px[1][2]=bs[i-1][j];
px[2][0]=rs[i][j];//存储该像素点的红色
px[2][1]=gs[i][j];
px[2][2]=bs[i][j];
px[3][0]=rs[i+1][j];//存储该像素点的红色
px[3][1]=gs[i+1][j];
px[3][2]=bs[i+1][j];
px[4][0]=rs[i][j+1];//存储该像素点的红色
px[4][1]=gs[i][j+1];
px[4][2]=bs[i][j+1];
for(int s=0;s<3;s++){
fm[s]=(int)((px[0][s]+px[1][s]+px[2][s]+px[3][s]+px[4][s])/5);
}
for(int s=0;s<5;s++){
dpx[s]=Math.sqrt((px[s][0]-fm[0])*(px[s][0]-fm[0])+
(px[s][1]-fm[1])*(px[s][1]-fm[1])+(px[s][2]-fm[2])*(px[s][2]-fm[2]));
}
int g=0;
double dest=0;
for(int s=0;s<5;s++){
if(s==0){
dest=dpx[s];
}
if(dest>dpx[s]){
dest=dpx[s];
g=s;
}
//System.out.println(dpx[s]);
}
rgb[0]=px[g][0];
rgb[1]=px[g][1];
rgb[2]=px[g][2];
destImage.setRGB(i-1,j-1, ImageUtil.encodeColor(rgb));
}
}
return destImage;
}
五、 效果展示
总代码包下载:https://download.csdn.net/download/yiyexy/12323645