lemonHe

主要关注FPGA信号处理和数字图像处理技术,欢迎交流 邮箱:heliminlemon@163.com

中值滤波matlab及FPGA实现

1
阅读(2235)

    中值滤波是一种统计排序滤波器,它使用一个像素领域中的灰度级的中值来代替该像素的值,对于某些类型的随机噪声,中值滤波可提供良好的去噪能力,且比相同尺寸的线性平滑滤波器带来的模糊更少。对于单极性或者双极性脉冲噪声,中值滤波尤其有效,因此对于被椒盐噪声污染的图像,往往可以选用中值滤波的方法来去噪。

    下面介绍一种快速中值滤波算法,并提供一种在FPGA上实现的思路,在进行中值滤波时通常选用3*3窗口,因此使用类似上一篇博文中的方法,调用移位寄存器IP核,输出3行数据,进入第一级3*3共9个寄存器缓存。

image  

(1) 第1个时钟周期,对a00和a01,a10和a11,a20和a21进行比较,大的放在前面,结果存入第2级3*3共9个寄存器;

(2) 第2个时钟周期,将a02分别和a00、a01,a12分别和a10、a11,a22分别a20、a21进行比较,并从左到右按从大到小排序,结果存入第3级3*3共9个寄存器;

(3) 第3个时钟周期,分别对列进行第一次排序,结果存入第4级3*3共9个寄存器;

(4) 第4个时钟周期,对列进行第二次排序,结果存入第5级3*3共9个寄存器中,经过4次比较,得到下图所示从左到右,从上到下都按从到大小的顺序排序的3*3窗口,通过简单分析可知,中值为a02、a11、a20中的一个,继续排序;

(5) 第5个时钟周期,对a02和a11进行排序,结果存入1*3共3个寄存器中;

(6) 第6个时钟周期,将a20分别和a02和a11进行排序,得到中值。

image  

    下面给出matlab实现的代码,可用作FPGA实现的参考

clc;
clear all;
close all;
im1 = imread('lena_salt.tif');      %原始图像
[m,n] = size(im1);
im2 = uint8(zeros(m,n));         %定义一滤波后图像
%为了实现对边缘的滤波,对图像进行扩展
im1_mid1 = uint16(zeros(m+2,n+2));  
im1_mid1(2:m+1,2:n+1) = im1;
im1_mid1(1,2:n+1) = im1_mid1(3,2:n+1);
im1_mid1(m+2,2:n+1) = im1_mid1(m,2:n+1);
im1_mid1(1:m+2,1) = im1_mid1(1:m+2,3);
im1_mid1(1:m+2,n+2) = im1_mid1(1:m+2,n+2);
%为了实现对边缘的滤波,对图像进行扩展
%定义3x3窗口,存储排序后的数据
im_mid1 = uint8(zeros(3,3));
im_mid2 = uint8(zeros(3,3));
im_mid3 = uint8(zeros(3,3));
im_mid4 = uint8(zeros(3,3));
im_mid5 = uint8(zeros(3,3));
for i=2:1:m+1
    for j=2:1:n+1
            %水平方向第1次调整顺序
            if(im1_mid1(i-1,j-1)>=im1_mid1(i-1,j))
                im_mid1(1,1) = im1_mid1(i-1,j-1);
                im_mid1(1,2) = im1_mid1(i-1,j);
                im_mid1(1,3) = im1_mid1(i-1,j+1);
            else
                im_mid1(1,1) = im1_mid1(i-1,j);
                im_mid1(1,2) = im1_mid1(i-1,j-1);
                im_mid1(1,3) = im1_mid1(i-1,j+1);
            end
            if(im1_mid1(i,j-1)>=im1_mid1(i,j))
                im_mid1(2,1) = im1_mid1(i,j-1);
                im_mid1(2,2) = im1_mid1(i,j);
                im_mid1(2,3) = im1_mid1(i,j+1);
            else
                im_mid1(2,1) = im1_mid1(i,j);
                im_mid1(2,2) = im1_mid1(i,j-1);
                im_mid1(2,3) = im1_mid1(i,j+1);
            end
            if(im1_mid1(i+1,j-1)>=im1_mid1(i+1,j))
                im_mid1(3,1) = im1_mid1(i+1,j-1);
                im_mid1(3,2) = im1_mid1(i+1,j);
                im_mid1(3,3) = im1_mid1(i+1,j+1);
            else
                im_mid1(3,1) = im1_mid1(i+1,j);
                im_mid1(3,2) = im1_mid1(i+1,j-1);
                im_mid1(3,3) = im1_mid1(i+1,j+1);
            end
            %水平方向第2次调整顺序
            %水平方向第2次调整顺序
            if(im_mid1(1,3)>=im_mid1(1,1))
                im_mid2(1,1) = im_mid1(1,3);
                im_mid2(1,2) = im_mid1(1,1);
                im_mid2(1,3) = im_mid1(1,2);
            else if(im_mid1(1,3)<im_mid1(1,1) && im_mid1(1,3)>im_mid1(1,2))
                    im_mid2(1,1) = im_mid1(1,1);
                    im_mid2(1,2) = im_mid1(1,3);
                    im_mid2(1,3) = im_mid1(1,2);
                else if(im_mid1(1,3)<=im_mid1(1,2))
                    im_mid2(1,:) = im_mid1(1,:);
                    end
                end
            end
            if(im_mid1(2,3)>=im_mid1(2,1))
                im_mid2(2,1) = im_mid1(2,3);
                im_mid2(2,2) = im_mid1(2,1);
                im_mid2(2,3) = im_mid1(2,2);
            else if(im_mid1(2,3)<im_mid1(2,1) && im_mid1(2,3)>im_mid1(2,2))
                    im_mid2(2,1) = im_mid1(2,1);
                    im_mid2(2,2) = im_mid1(2,3);
                    im_mid2(2,3) = im_mid1(2,2);
                else if(im_mid1(2,3)<=im_mid1(2,2))
                    im_mid2(2,:) = im_mid1(2,:);
                    end
                end
            end            
            if(im_mid1(3,3)>=im_mid1(3,1))
                im_mid2(3,1) = im_mid1(3,3);
                im_mid2(3,2) = im_mid1(3,1);
                im_mid2(3,3) = im_mid1(3,2);
            else if(im_mid1(3,3)<im_mid1(3,1) && im_mid1(3,3)>im_mid1(3,2))
                    im_mid2(3,1) = im_mid1(3,1);
                    im_mid2(3,2) = im_mid1(3,3);
                    im_mid2(3,3) = im_mid1(3,2);
                else if(im_mid1(3,3)<=im_mid1(3,2))
                    im_mid2(3,:) = im_mid1(3,:);
                    end
                end
            end            
            %水平方向第2次调整顺序
            %垂直方向第1次调整顺序
            if(im_mid2(1,1)>=im_mid2(2,1))
                im_mid3(1,1) = im_mid2(1,1);
                im_mid3(2,1) = im_mid2(2,1);
                im_mid3(3,1) = im_mid2(3,1);
            else
                im_mid3(1,1) = im_mid2(2,1);
                im_mid3(2,1) = im_mid2(1,1);
                im_mid3(3,1) = im_mid2(3,1);
            end
            if(im_mid2(1,2)>=im_mid2(2,2))
                im_mid3(1,2) = im_mid2(1,2);
                im_mid3(2,2) = im_mid2(2,2);
                im_mid3(3,2) = im_mid2(3,2);
            else
                im_mid3(1,2) = im_mid2(2,2);
                im_mid3(2,2) = im_mid2(1,2);
                im_mid3(3,2) = im_mid2(3,2);
            end                
            if(im_mid2(1,3)>=im_mid2(2,3))
                im_mid3(1,3) = im_mid2(1,3);
                im_mid3(2,3) = im_mid2(2,3);
                im_mid3(3,3) = im_mid2(3,3);
            else
                im_mid3(1,3) = im_mid2(2,3);
                im_mid3(2,3) = im_mid2(1,3);
                im_mid3(3,3) = im_mid2(3,3);
            end
            %垂直方向第1次调整顺序
            %垂直方向第2次调整顺序
            if(im_mid3(3,1)>=im_mid3(1,1))
                im_mid4(1,1) = im_mid3(3,1);
                im_mid4(2,1) = im_mid3(1,1);
                im_mid4(3,1) = im_mid3(2,1);
            else if(im_mid3(3,1)<im_mid3(1,1) && im_mid1(3,1)>im_mid1(2,1))
                    im_mid4(1,1) = im_mid1(1,1);
                    im_mid4(2,1) = im_mid1(3,1);
                    im_mid4(3,1) = im_mid1(2,1);
                else if(im_mid3(1,3)<=im_mid3(1,2))
                    im_mid4(:,1) = im_mid3(:,1);
                    end
                end
            end
            if(im_mid3(3,2)>=im_mid3(1,2))
                im_mid4(1,2) = im_mid3(3,2);
                im_mid4(2,2) = im_mid3(1,2);
                im_mid4(3,2) = im_mid3(2,2);
            else if(im_mid3(3,2)<im_mid3(1,2) && im_mid1(3,2)>im_mid1(2,2))
                    im_mid4(1,2) = im_mid1(1,2);
                    im_mid4(2,2) = im_mid1(3,2);
                    im_mid4(3,2) = im_mid1(2,2);
                else if(im_mid3(1,3)<=im_mid3(1,2))
                    im_mid4(:,2) = im_mid3(:,2);
                    end
                end
            end            
            if(im_mid3(3,3)>=im_mid3(1,3))
                im_mid4(1,3) = im_mid3(3,3);
                im_mid4(2,3) = im_mid3(1,3);
                im_mid4(3,3) = im_mid3(2,3);
            else if(im_mid3(3,3)<im_mid3(1,3) && im_mid1(3,3)>im_mid1(2,3))
                    im_mid4(1,3) = im_mid1(1,3);
                    im_mid4(2,3) = im_mid1(3,3);
                    im_mid4(3,3) = im_mid1(2,3);
                else if(im_mid3(1,3)<=im_mid3(1,3))
                    im_mid4(:,3) = im_mid3(:,3);
                    end
                end
            end
            %垂直方向第2次调整顺序
            %对角线方向调整顺序
            if(im_mid4(1,3)>im_mid4(2,2) && im_mid4(2,2)>im_mid4(3,1))
                im_mid5(1,3) = im_mid4(1,3);
                im_mid5(2,2) = im_mid4(2,2);
                im_mid5(3,1) = im_mid4(3,1);
            else if(im_mid4(1,3)>im_mid4(3,1) && im_mid4(3,1)>im_mid4(2,2))
                    im_mid5(1,3) = im_mid4(1,3);
                    im_mid5(2,2) = im_mid4(3,1);
                    im_mid5(3,1) = im_mid4(2,2);
                else if(im_mid4(2,2)>im_mid4(1,3) && im_mid4(1,3)>im_mid4(3,1))
                        im_mid5(1,3) = im_mid4(2,2);
                        im_mid5(2,2) = im_mid4(1,3);
                        im_mid5(3,1) = im_mid4(3,1);
                    else if(im_mid4(2,2)>im_mid4(3,1) && im_mid4(3,1)>im_mid4(1,3))
                            im_mid5(1,3) = im_mid4(2,2);
                            im_mid5(2,2) = im_mid4(3,1);
                            im_mid5(3,1) = im_mid4(1,3);
                        else if(im_mid4(3,1)>im_mid4(2,2) && im_mid4(2,2)>im_mid4(1,3))
                                im_mid5(1,3) = im_mid4(3,1);
                                im_mid5(2,2) = im_mid4(2,2);
                                im_mid5(3,1) = im_mid4(1,3);
                            else if(im_mid4(3,1)>im_mid4(1,3) && im_mid4(1,3)>im_mid4(2,2))
                                im_mid5(1,3) = im_mid4(3,1);
                                im_mid5(2,2) = im_mid4(1,3);
                                im_mid5(3,1) = im_mid4(2,2);
                                else
                                    im_mid5(1,3) = im_mid4(1,3);
                                    im_mid5(2,2) = im_mid4(2,2);
                                    im_mid5(3,1) = im_mid4(3,1);
                                end
                            end
                        end
                    end
                end
            end         
            im2(i-1,j-1) = im_mid5(2,2);
    end
end
subplot(1,2,1);
imshow(im1);
subplot(1,2,2);
imshow(uint8(im2));

测试结果如下,输入一幅被椒盐噪声污染的图像,输出滤波后的图像,效果还是很nice的。

image  

上面的代码实现效率很低,不过对于FPGA板级实现倒是挺有参考价值,mathworks库中带有medfilt2函数,在matlab中可以地调用对于上位机上的中值滤波,建议用库中的函数。

 

参考:

1. 数字图像处理,Gonzalez

2. 图像实时滤波方法及其FPGA实现,杨免艳