威尼斯www.9778.com-威尼斯正版官方网站

verilog 实现中值滤波

日期:2019-12-25编辑作者:编程人生

某个博客叙述原理如下:在描述自适应中值滤波器时需要用到如下的符号:(Z_{min}=S_{xy})中的最小灰度值(Z_{max}=S_{xy})中的最大灰度值(Z_{med}=S_{xy})中的灰度值的中值(Z_{xy})表示坐标((x,y))处的灰度值(S_{max}=S_{xy})允许的最大窗口尺寸自适应中值滤波器有两个处理过程,分别记为:A和B。A:A1=(Z_{med}-Z_{min})A2=(Z_{med}-Z_{max})如果A10且A20,跳转到B;否则,增大窗口的尺寸如果增大后窗口的尺寸(leqS_{max}),则重复A过程。否则,输出(Z_{med})B:B1=(Z_{xy}-Z_{min})B2=(Z_{xy}-Z_{max})如果B10且B20,则输出(Z_{xy})否则输出(Z_{med})自适应中值滤波原理说明过程A的目的是确定当前窗口内得到中值(Z_{med})是否是噪声。如果(Z_{min}Z_{med}Z_{max}),则中值(Z_{med})不是噪声,这时转到过程B测试,当前窗口的中心位置的像素(Z_{xy})是否是一个噪声点。如果(Z_{min}Z_{xy}Z_{max}),则(Z_{xy})不是一个噪声,此时滤波器输出(Z_{xy});如果不满足上述条件,则可判定(Z_{xy})是噪声,这是输出中值(Z_{med})。如果在过程A中,得到则(Z_{med})不符合条件(Z_{min}Z_{med}Z_{max}),则可判断得到的中值(Z_{med})是一个噪声。在这种情况下,需要增大滤波器的窗口尺寸,在一个更大的范围内寻找一个非噪声点的中值,直到找到一个非噪声的中值,跳转到B;或者,窗口的尺寸达到了最大值,这时返回找到的中值,退出。问题是:如果(Z_{min}Z_{med}Z_{max}),则中值(Z_{med})不是噪声,这时转到过程B测试,但是,,,中值肯定在最大和最小之间啊??这句话是什么意思呢?

  1. 对比度增强
      该方法按照一定规则逐点改变像素灰度,从而改变像素灰度范围,达到增强对比度的目的。若输入图像为f(x,y),输出图像为g(x,y),则对比度增强可以表示为:
      g(x,y)=T[f(x,y)]
      其中T[.]表示输出像素灰度和对应的输入像素灰度之间的映射关系。该映射关系有以下几种:
    1) 线形映射
       若原图像的灰度范围为[B1,E1],而期待的输出灰度范围为[B2,E2],则线形变换
       g(x,y) = [(E2-B2)/(E1-B1)]*[f(x,y)-B1]+B2;
       可以满足这一要求。
    2) 分段线形映射
    3) 非线形映射
       从原理上讲,T[.]可以为任何非线形数学函数,例如平方、指数、对数、幂等变换等,但通常我们使用的是对数变换或幂变换。
       g(x,y) = Clog[f(x,y)+1]
      式中C用于使变换后的像素灰度在合适的范围。常见的珈玛校正用的就是对数变换。
    4) 其它映射关系
       <1> 灰度切片
           即取出一小段灰度范围对其加以拉伸后进行观察。
       <2> 锯齿型变换   
  2. 修正直方图增强
       直方图增强技术使用图像直方图作为图像增强的依据,使变换后的图像的直方图成为期望的形状。这种技术可以增加对比度并消除噪声。
    1) 直方图均衡
    2) 直方图规定化
       有两点要注意:其一,该方法要求函数的反函数,在离散的数字图像上比较容易处理。其二,定制合适的直方图比较困难。
  3. 平滑
    平滑技术用于消除图像中的噪声。可以在时域通过求邻域平均实现,也可以在频域通过低通滤波实现。
    1) 邻域平均
       该方法比较简单。这里提几点对该方法的改进以避免对图像信号本身的平滑(主要是减小边界信息的损失):
       <1> 门限法
           当像素灰度高出平均值某个值时才进行替代,否则保持其原始值不变。
       <2> 加权法
           即按照距离或其它因素对像素和其邻域赋予不同的权重。
       <3> 选择平均法
           即不必使用窗口内的所有像素点,而是有选择性的使用。比如最接近中心像素灰度的几个像素点,或与之灰度差小于方差的那些像素点。
       <4> 子窗统计法
           即将窗口内像素排序后分为两组:A和B,计算其灰度平均值,若两平均值之差过大,则该子窗包含边界,中心像素与A组的5点进行6点平均,否则应进行9点平均。

    另外还有一些非线形的邻域平均方法,例如几何均值和逆滤波均值法,但其计算量相对较大。

    2) 中值滤波
       中值滤波是滤除椒盐噪声的有效方法,但也会滤除细线和小的目标区域。实验表明,当出现的正负脉冲噪声概率超过20%时,使用中值滤波后可能产生比较严重的失真,此时应考虑改进的中值滤波算法——自适应中值滤波。
       自适应中值滤波的步骤如下:
       设A0为对像素点(i,j)进行中值滤波的工作窗口,f(i,j)为像素点(i,j)的灰度值,f_med为A0窗口中的中值,f_min,f_max分别为最大和最小值,A_max为允许的最大窗口。
       <1> 计算z1 = f_med - f_min,z2 = f_med - f_max;
       <2> 若z1 > 0和z2 < 0,则转到<3>;否则增大窗口A0尺寸,若A0<A_max,则重复<1>和<2>,否则输出f(i,j);
       <3> 计算g1 = f(i,j) - f_min, z2 = f(i,j) - f_max;
       <4> 若g1>0和g2<0,则输出f(i,j),否则输出f_med;
    在上述算法中,若f_min<f_med<f_max,则表明f_med不是噪声,转至<3>,然后判断f(i,j)是否是噪声,当f_med和f(i,j)均不为噪声时,优先输出f(i,j)。

    (3) 频域滤波
        主要在于对图像做FFT变换。

 

图像增强的优劣评估主要采用主观方法。一般包括以下几种图像增强方法:

中值滤波

将 3*3 滑动块中的灰度值进行排序,然后用排序的中间值取代 3*3 滑块中心的值。示意图如下图所示。

图片 1

 


中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘少受模糊。


图像信号在形成、传输和记录的过程中,由于成像系统、传输介质、工作环境和记录设备等的固有缺陷,不可避免地产生各种类型的噪声,降低了图像的质量,进而影响后续处理(如边缘检测、图像分割、特征提取、模式识别等)的效果或准确性。因此,对噪声图像进行滤波是必要预处理过程。但滤波算法在去除噪声的同时难免对图像造成一定程度的模糊,造成细节信息的丢失。

实现原理(这是文献中的,理解起来比较复杂,最近我又学到一种更加简单快捷的方法,补充在最后)

通过如下图所示的6级比较电路路输出中值,其输人数据为图1所示的滤波掩膜所在的图像数据。第一级比较电路由3个三输入比较器C组成,每个比较器的输出数据依序排列(参见图示)。将3组比较结果中最小的3个数放在一起、中间的3个数放在一起、最大的3个数放在一起,参加第二级比较。第二级比较电路的原理与第一级类似,输出out1和out9,分别是输入数据中的最大值和最小值,这2个数据将被舍去不参加下一级比较。参加第三级比较的有7个数据,其原理类似于前两级比较电路,输出out2和out8分别是该7个数据的最大值和最小值,并且被舍去,仅留下5个数据参加第四级比较。剩下的几级比较电路以类似于先前的原理进行比较。如此,经过6级比较后即可得到9个数据的标准中值滤波输出值out5,而outl,out2,⋯,out9分别是这9个数据从最大到最小的顺序排列值。此外。为了保证流水线操作过程中数据的同步性,在第三级和第五级比较电路中需要插入数据寄存器R缓存当前该级中不参与比较的数据。

 

图片 2

 

 


说明:中值滤波也是基于3*3的像素矩阵,有关3*3矩阵的实现,在上一篇文章中详细讲过链接如下:。

此原理多次用到比较器,我将比较器分为两类,第一类:三个数进行比较,输出max、med、min。第二类:两个数进行比较,输出max、min。

第一类比较器的实现

module compare_1(
             data_a    ,
             data_b    ,
             data_c    ,
             data_max  ,
             data_min  ,
             data_med
             );

input    [5:0]   data_a  ;
input    [5:0]   data_b  ;
input    [5:0]   data_c  ;

output   [5:0]   data_max;
output   [5:0]   data_min;
output   [5:0]   data_med;

wire     [5:0]   data_max;
wire     [5:0]   data_min;
wire     [5:0]   data_med;

wire [5:0] a,b,c;//a,b,c代替三个输入,方便代码书写
assign a=data_a;
assign b=data_b;
assign c=data_c;

assign data_med =  (a<b)?(b<c)?b:(a>c)?a:c : (b>c)?b:(a<c)?a:c;
assign data_min =  (a<b)?(a<c)?a:c  :  (b>c)?c:b    ;
assign data_max =  (a>b)?(a>c)?a:c :  (b>c)?b:c    ;

endmodule

第二类比较器就是比较两个数大小,非常简单。

module compare_2 (
           dat_1   ,
           dat_2   ,
           dat_max ,
           dat_min
);

input   [5:0] dat_1  ;
input   [5:0] dat_2  ;
output  [5:0] dat_max;
output  [5:0] dat_min;

wire   [5:0] dat_max;
wire   [5:0] dat_min;

assign dat_max=(dat_1>dat_2)? dat_1:dat_2;
assign dat_min=(dat_1>dat_2)? dat_2:dat_1;

endmodule

然后不断调用一类和二类比较器,实现六级比较电路

//---------------------------------------------------------------------- 第一阶段
// 第一阶段  max11 第一阶段1



          compare u11_compare(

             .data_a   (p_11) ,  // 3*3矩阵第一行第一个数
             .data_b   (p_12) ,  //  第二个
             .data_c   (p_13),  // 第三个
             .data_max  (max11),
             .data_min  (min11),
             .data_med (med11)

             );
  //求第二行的最大值,最小值,中间值
compare  u12_compare(         
          .data_a  (p_21), //3*3矩阵第二行
          .data_b  (p_22),//
          .data_c  (p_23),//
          .data_max(max12),
          .data_min(min12),
          .data_med(med12));

 //求第三行的最大值,最小值,中间值
compare  u13_compare(          
          .data_a  (p_31)  ,  //3*3矩阵第三行
          .data_b  (p_32)  ,//
          .data_c  (p_33)  ,//
          .data_max(max13) ,
          .data_min(min13) ,
          .data_med(med13)
          );

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
         max_p1_1<=0;  //第一行的最大数
         max_p1_2<=0; //            中间数
         max_p1_3<=0; //            最小数       
         min_p1_1<=0;  //第二行的最大数
         min_p1_2<=0;  //            中间数
         min_p1_3<=0;  //            最小数  
         med_p1_1<=0; //第三行
         med_p1_2<=0;
         med_p1_3<=0;
    end
    else if(per_href_ff1==1&&flag_do==1)begin
         max_p1_1<=max11;
         max_p1_2<=max12;
         max_p1_3<=max13;
         min_p1_1<=min11;
         min_p1_2<=min12;
         min_p1_3<=min13;
         med_p1_1<=med11;
         med_p1_2<=med12;
         med_p1_3<=med13;
    end
    else begin
         max_p1_1<=0;
         max_p1_2<=0;
         max_p1_3<=0;
         min_p1_1<=0;
         min_p1_2<=0;   
         min_p1_3<=0; 
         med_p1_1<=0;   
         med_p1_2<=0;
         med_p1_3<=0;
    end
end
//---------------------------------------------------------------------- 第二阶段 


 //最大值的大中小
compare u14_compare(          
          .data_a  (max_p1_1)  ,
          .data_b  (max_p1_2)  ,
          .data_c  (max_p1_3)  ,
          .data_max(max_2_max) ,
          .data_min(max_2_min) ,
          .data_med(max_2_med)

                    );
//最小值中的大中小
compare u15_compare(           
          .data_a  (min_p1_1)  ,
          .data_b  (min_p1_2)  ,
          .data_c  (min_p1_3)  ,
          .data_max(min_2_max) ,
          .data_min(min_2_min) ,
          .data_med(min_2_med)

                    );
 //中的大中小
compare u16_compare(          
          .data_a  (med_p1_1)  ,
          .data_b  (med_p1_2)  ,
          .data_c  (med_p1_3)  ,
          .data_max(med_2_max) ,
          .data_min(med_2_min) ,
          .data_med(med_2_med)

                    );                    

 always  @(posedge clk or negedge rst_n)begin
     if(rst_n==1'b0)begin
      //max_p2_max<=0;
      max_p2_min<=0;
      max_p2_med<=0;
      min_p2_max<=0;
     // min_p2_min<=0;
      min_p2_med<=0;
      med_p2_max<=0;
      med_p2_min<=0;
      med_p2_med<=0;
     end
     else if(per_href_ff2==1&&flag_do==1) begin
     //  max_p2_max<= max_2_max; //舍弃最大值
       max_p2_min<= max_2_min;
       max_p2_med<= max_2_med;                             
       min_p2_max<= min_2_max;
      // min_p2_min<= min_2_min;//舍弃的最小值
       min_p2_med<= min_2_med;
       med_p2_max<= med_2_max ;
       med_p2_min<= med_2_min ;
       med_p2_med<= med_2_med ;
     end
     else begin
       // max_p2_max<=0;
        max_p2_min<=0;
        max_p2_med<=0;                      
        min_p2_max<=0;
     //   min_p2_min<=0;
        min_p2_med<=0;                      
        med_p2_max<=0;
        med_p2_min<=0;
        med_p2_med<=0;
    end

 end
//----------------------------------------------------------------------第三阶段ff4


 //最大
compare u17_compare(        

            . data_a  (max_p2_med),  
            . data_b  (min_p2_max),
            . data_c  (med_p2_max),
            . data_max(),
            . data_min(max_3_min),
            . data_med(max_3_med)

             );
//最小
  compare u18_compare(        

            . data_a  (max_p2_min),
            . data_b  (med_p2_min), 
            . data_c  (min_p2_med),
            . data_max(min_3_max),
            . data_min(),
            . data_med(min_3_med)

             );


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       max_p3_med  <=0 ;
       max_p3_min  <=0 ;
       med_p3      <=0 ;
       min_p3_max  <=0 ;
       min_p3_med  <=0 ;
    end            
    else if(per_href_ff3==1&&flag_do==1)begin
       max_p3_med  <= max_3_med ;
       max_p3_min  <= max_3_min ;
       med_p3      <= med_p2_med; 
       min_p3_max  <= min_3_max ;
       min_p3_med  <= min_3_med ;
    end
    else begin
       max_p3_med  <=0 ;
       max_p3_min  <=0 ;
       med_p3      <=0 ;
       min_p3_max  <=0 ;
       min_p3_med  <=0 ;
    end

end

//----------------------------------------------------------------------第4阶段 


compare_2  u1_compare_2(               
           .dat_1   (max_p3_med) ,
           .dat_2   (max_p3_min),
           .dat_max (max_4_max),
           .dat_min (max_4_min)
           );


compare u19_compare(
            . data_a  (med_p3),
            . data_b  (min_p3_max),
            . data_c  (min_p3_med),
            . data_max(min_4_max),
            . data_min(min_4_med),
            . data_med(min_4_min)

             );

 always  @(posedge clk or negedge rst_n)begin
     if(rst_n==1'b0)begin
        max_p4_max    <=0 ;
        max_p4_min    <=0 ;
        min_p4_max    <=0 ;
        min_p4_med    <=0 ;
        min_p4_min    <=0 ;
     end
     else if(per_href_ff4&&flag_do==1)begin
        max_p4_max    <=max_4_max ;
        max_p4_min    <=max_4_min ;
        min_p4_max    <=min_4_max ;
        min_p4_med    <=min_4_med ;
        min_p4_min    <=min_4_min ;

     end
     else begin
        max_p4_max    <=0 ;
        max_p4_min    <=0 ;
        min_p4_max    <=0 ;
        min_p4_med    <=0 ;
        min_p4_min    <=0 ;
     end
 end



//----------------------------------------------------------------------第5阶段


compare_2  u2_compare_2(    

           .dat_1   ( max_p4_max),
           .dat_2   ( min_p4_max),
           .dat_max (),
           .dat_min (max_5_min)
                       );
  //
compare_2  u3_compare_2(   

           .dat_1   ( min_p4_min),
           .dat_2   ( max_p4_min),
           .dat_max (min_5_max),
           .dat_min ()
                       );

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
         max_p5_min<=0;
         min_p5_max<=0;
         med_p5    <=0;

    end
    else if(per_href_ff5==1&&flag_do) begin
         max_p5_min<= max_5_min;
         min_p5_max<= min_5_max;
         med_p5    <= min_p4_med;

    end
end

//----------------------------------------------------------------------第6阶段。
 //

compare u10_compare(        

            .data_a  (max_p5_min),
            .data_b  (min_p5_max),
            .data_c  (med_p5    ),
            .data_max(max_6_max),
            .data_min(max_6_min),
            .data_med(max_6_med)

             );

处理后的结果

图片 3

补充 :

快速排序法实现中值滤波

图片 4

第一步:将每一行按最大值、中间值、最小值排列

第二步:提取出最大值的最小值,中间值的中间值,最小值的最大值

第三步:将第二步提取出来的三个数进行排序,中间值即我们要求的中间值。

代码很简单,就不写了。

 

 转载请注明出处:

 

  

本文由威尼斯www.9778.com发布于编程人生,转载请注明出处:verilog 实现中值滤波

关键词:

windows宗旨编程-Windows VC++编制程序难题,怎么着收获文件粘贴事

需求描述:我想实现office内容的复制粘贴功能,即在本机上复制文档某部分内容,然后粘贴到我的应用程序上,并且...

详细>>

C++ 向Excel中写字符串

我用的类是这几个:CApplicationapp;CWorkbookbook;//工作薄CWorkbooksbooks;//工作薄集合CWorksheetsheet;//工作表CWorksheetssheets;//工作...

详细>>

怎么使用com的回调

有2个类,CCDMAX和CCDMAXEvents。 classCCDMAX:publicCOleDispatchDriver{public:CCDMAX(){}//调用COleDispatchDriver默认构造函数CCDMAX(LPDISPAT...

详细>>

MFC操作word获取当前页的页码

COleVariantcovZero((short)0),covTrue((short)TRUE);wd.m_wdView.SetSeekView(10);//wdSeekCurrentPageFooter=10wd.m_wdParagraphFormat=wd.m_wdSel.GetParagrap...

详细>>