参考:小梅哥的《FPGA系统设计与验证实战指南》

一、算法介绍

中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值.

中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W 为二维模板,通常为 33,55 区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。

中值滤波法对消除椒盐噪声非常有效,在光学测量条纹图象的相位分析处理方法中有特殊作用,但在条纹中心分析方法中作用不大。中值滤波在图像处理中,常用于保护边缘信息,是经典的平滑噪声的方法。

要得到模板中数据的中间值,首先要将数据按大小排序,然后根据有序的数字序列来找中问值。中值滤波排序的过程有很多成熟的算法,如冒泡排序、二分排序等,大多是基于微机平台的软件算法,而适合硬件平台的排序算法则比较少。

FPGA 中值滤波实现方法:

(摘自:https://blog.csdn.net/Laplace666/article/details/83826443)

中值滤波方法是,对待处理的当前像素,选择一个模板,该模板为其邻近的若干个像素组成,对模板的像素由小到大进行排序,再用模板的中值来替代原像素的值的方法。

当我们使用3x3窗口后获取邻域中的9个像素,就需要对9个像素值进行排序,为了提高排序效率,排序算法思想如下图所示:

(1) 对窗内的每行像素按降序排序,得到最大值、中间值和最小值;

(2) 把三行的最小值相比较,取其中的最大值;

(3) 把三行的最大值相比较,取其中的最小值;

(4) 把三行的中间值相比较,再取一次中间值;

(5) 把前面得到的三个值再做一次排序,获得的中值即该窗口的中值。

二、程序设计

关于如何形成3*3的像素矩阵,参考另一篇文章:FPGA丨设计行缓存(linebuffer)对图像开窗

timescale 1ns/1ps
module median_filtering(input clk,input rst_n,input [15:0] data_in,input data_in_en,input hs_in,input vs_in,output[15:0] data_out,output data_out_en,output hs_out,output vs_out);wire [15:0] line0;
wire [15:0] line1;
wire [15:0] line2;
//--------------------------------------
//pipeline control signal
//--------------------------------------
reg hs0;
reg hs1;
reg hs2;
reg vs0;
reg vs1;
reg vs2;
reg de0;
reg de1;
reg de2;
//-------------------------------------
//pipeline data 对应3*3窗口内的九个像素
//-------------------------------------
reg [15:0] line0_data0;
reg [15:0] line0_data1;
reg [15:0] line0_data2;reg [15:0] line1_data0;
reg [15:0] line1_data1;
reg [15:0] line1_data2;reg [15:0] line2_data0;
reg [15:0] line2_data1;
reg [15:0] line2_data2;
//--------------------------------------
//define line max mid min
//--------------------------------------
reg [15:0] line0_max;
reg [15:0] line0_mid;
reg [15:0] line0_min;reg [15:0] line1_max;
reg [15:0] line1_mid;
reg [15:0] line1_min;reg [15:0] line2_max;
reg [15:0] line2_mid;
reg [15:0] line2_min;
//----------------------------------------------------------------
// define //max of min //mid of mid// min of max
//---------------------------------------------------------------
reg [15:0] max_max;
reg [15:0] max_mid;
reg [15:0] max_min;reg [15:0] mid_max;
reg [15:0] mid_mid;
reg [15:0] mid_min;reg [15:0] min_max;
reg [15:0] min_mid;
reg [15:0] min_min;
//---------------------------------------------
// define mid of mid
//---------------------------------------------
reg [15:0] mid;
line3x3 line3x3_inst(.clken(data_in_en),.clock(clk),.shiftin(data_in),.shiftout(),.taps0x(line0),.taps1x(line1),.taps2x(line2));
//----------------------------------------------------
//delay control signal
//----------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginhs0 <= 1'b0;hs1 <= 1'b0;hs2 <= 1'b0;vs0 <= 1'b0;vs1 <= 1'b0;vs2 <= 1'b0;de0 <= 1'b0;de1 <= 1'b0;de2 <= 1'b0;endelse if(data_in_en) beginhs0 <= hs_in;hs1 <= hs0;hs2 <= hs1;vs0 <= vs_in;vs1 <= vs0;vs2 <= vs1;de0 <= data_in_en;de1 <= de0;de2 <= de1; end
end
//--------------------------------------------------------------------
// Form an image matrix of three multiplied by three
//--------------------------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline0_data0 <= 16'b0;line0_data1 <= 16'b0;line0_data2 <= 16'b0;line1_data0 <= 16'b0;line1_data1 <= 16'b0;line1_data2 <= 16'b0;line2_data0 <= 16'b0;line2_data1 <= 16'b0;line2_data2 <= 16'b0;endelse if(data_in_en) beginline0_data0 <= line0;line0_data1 <= line0_data0;line0_data2 <= line0_data1;line1_data0 <= line1;line1_data1 <= line1_data0;line1_data2 <= line1_data1;line2_data0 <= line2;line2_data1 <= line2_data0;line2_data2 <= line2_data1; endelse ;
end
//--------------------------------------------------------------------------
//(line0 line1 line2) of (max mid min)
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline0_max <= 16'd0;line0_mid <= 16'd0;line0_min <= 16'd0;endelse if(data_in_en) beginif((line0_data0 >= line0_data1) && (line0_data0 >= line0_data2)) beginline0_max <= line0_data0;if(line0_data1 >= line0_data2) beginline0_mid <= line0_data1;line0_min <= line0_data2;endelse beginline0_mid <= line0_data2;line0_min <= line0_data1;endendelse if((line0_data1 > line0_data0) && (line0_data1 >= line0_data2)) beginline0_max <= line0_data1;if(line0_data0 >= line0_data2) beginline0_mid <= line0_data0;line0_min <= line0_data2;endelse beginline0_mid <= line0_data2;line0_min <= line0_data0;endendelse if((line0_data2 > line0_data0) && (line0_data2 > line0_data1)) beginline0_max <= line0_data2;if(line0_data0 >= line0_data1) beginline0_mid <= line0_data0;line0_min <= line0_data1;endelse beginline0_mid <= line0_data1;line0_min <= line0_data0;endendend
end
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline1_max <= 16'd0;line1_mid <= 16'd0;line1_min <= 16'd0;endelse if(data_in_en) beginif((line1_data0 >= line1_data1) && (line1_data0 >= line1_data2)) beginline1_max <= line1_data0;if(line1_data1 >= line1_data2) beginline1_mid <= line1_data1;line1_min <= line1_data2;endelse beginline1_mid <= line1_data2;line1_min <= line1_data1;endendelse if((line1_data1 > line1_data0) && (line1_data1 >= line1_data2)) beginline1_max <= line1_data1;if(line1_data0 >= line1_data2) beginline1_mid <= line1_data0;line1_min <= line1_data2;endelse beginline1_mid <= line1_data2;line1_min <= line1_data0;end endelse if((line1_data2 > line1_data0) && (line1_data2 > line1_data1)) beginline1_max <= line1_data2;if(line1_data0 >= line1_data1) beginline1_mid <= line1_data0;line1_min <= line1_data1;endelse beginline1_mid <= line1_data1;line1_min <= line1_data0;end endend
end
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline2_max <= 16'd0;line2_mid <= 16'd0;line2_min <= 16'd0;endelse if(data_in_en) beginif((line2_data0 >= line2_data1) && (line2_data0 >= line2_data2)) beginline2_max <= line2_data0;if(line2_data1 > line2_data2) beginline2_mid <= line2_data1;line2_min <= line2_data2;endelse beginline2_mid <= line2_data2;line2_min <= line2_data1;endendelse if((line2_data1 > line2_data0) && (line2_data1 >= line2_data2)) beginline2_max <= line2_data1;if(line2_data0 >= line2_data2) beginline2_mid <= line2_data0;line2_min <= line2_data2;endelse beginline2_mid <= line2_data2;line2_min <= line2_data0;end endelse if((line2_data2 > line2_data0) && (line2_data2 > line2_data1)) beginline2_max <= line2_data2;if(line2_data0 >= line2_data1) beginline2_mid <= line2_data0;line2_min <= line2_data1;endelse beginline2_mid <= line2_data1;line2_min <= line2_data0;end endend
end
//--------------------------------------------------------------------------
// (max_max max_mid max_min) of ((line0 line1 line2) of max)
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginmax_max <= 16'd0;max_mid <= 16'd0;max_min <= 16'd0;endelse if(data_in_en) beginif((line0_max >= line1_max) && (line0_max >= line2_max)) beginmax_max <= line0_max;if(line1_max >= line2_max) beginmax_mid <= line1_max;max_min <= line2_max;endelse beginmax_mid <= line2_max;max_min <= line1_max;endendelse if((line1_max > line0_max) && (line1_max >= line2_max)) beginmax_max <= line1_max;if(line0_max >= line2_max) beginmax_mid <= line0_max;max_min <= line2_max;endelse beginmax_mid <= line2_max;max_min <= line0_max;endendelse if((line2_max > line0_max) && (line2_max > line1_max)) beginmax_max <= line2_max;if(line0_max >= line1_max) beginmax_mid <= line0_max;max_min <= line1_max;endelse beginmax_mid <= line1_max;max_min <= line0_max;endendend
end
//--------------------------------------------------------------------------
// (mid_max mid_mid mid_min) of ((line0 line1 line2)of mid)
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginmid_max <= 16'd0;mid_mid <= 16'd0;mid_min <= 16'd0;endelse if(data_in_en) beginif((line0_mid >= line1_mid) && (line0_mid >= line2_mid)) beginmid_max <= line0_mid;if(line1_mid >= line2_mid) beginmid_mid <= line1_mid;mid_min <= line2_mid;endelse beginmid_mid <= line2_mid;mid_min <= line1_mid;endendelse if((line1_mid > line0_mid) && (line1_mid >= line2_mid)) beginmid_mid <= line1_mid;if(line0_mid >= line2_mid) beginmid_mid <= line0_mid;mid_min <= line2_mid;endelse beginmid_mid <= line2_mid;mid_min <= line0_mid;endendelse if((line2_mid > line0_mid) && (line2_mid > line1_mid)) beginmid_max <= line2_mid;if(line0_mid >= line1_mid) beginmid_mid <= line0_mid;mid_min <= line1_mid;endelse beginmid_mid <= line1_mid;mid_min <= line0_mid;endendend
end
//--------------------------------------------------------------------------
// (min_max min_mid min_min) of ((line0 line1 line2)of min)
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginmin_max <= 16'd0;min_mid <= 16'd0;min_min <= 16'd0;endelse if(data_in_en) beginif((line0_min >= line1_min) && (line0_min >= line2_min)) beginmin_max <= line0_min;if(line1_min >= line2_min) beginmin_mid <= line1_min;min_min <= line2_min;endelse beginmin_mid <= line2_min;min_min <= line1_min;endendelse if((line1_min > line0_min) && (line1_min >= line2_min)) beginmin_max <= line1_min;if(line0_min >= line2_min) beginmin_mid <= line0_min;min_min <= line2_min;endelse beginmin_mid <= line2_min;min_min <= line0_min;endendelse if((line2_min > line0_min) && (line2_min > line1_min)) beginmin_max <= line2_min;if(line0_min >= line1_min) beginmin_mid <= line0_min;min_min <= line1_min;endelse beginmin_mid <= line1_min;min_min <= line0_min;endendend
end
//--------------------------------------------------------------------------
// middle
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n)mid <= 16'd0;else if(data_in_en) beginif(((max_min >= mid_mid) && (max_min < min_max)) || ((max_min >= min_max) &&
(max_mid < mid_mid)))mid <= max_min ;else if(((mid_mid > max_min ) && (mid_mid < min_max)) || ((min_mid >= min_max) &&
(mid_mid < max_min )))mid <= mid_mid;else if(((min_max> max_min ) && (min_max< mid_mid)) || ((min_max> mid_mid) &&
(mid_min < max_min )))mid <= min_max;endelse ;
end
//--------------------------------------------------------------------------
//result
//--------------------------------------------------------------------------
assign data_out = mid;
assign data_out_en = de2;
assign hs_out = hs2;
assign vs_out = vs2;
endmodule

需要注意的是:

上述代码的输入图像数据默认是灰度图像的数据,数据位宽为16。关于如何得到灰度图,可以参考另一篇文章:

FPGA丨RGB转Gray算法实现(rgb2ycbcr)

FPGA丨中值滤波算法实现相关推荐

  1. 滑动窗口滤波 c语言,关于中值滤波算法,以及C语言实现(转)

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

  2. 实时高速实现改进型中值滤波算法_爱学术_免费下载

    [摘要]在图像采集和处理过程中会引入噪声,必须先对图像进行预处理.本文介绍一种快速中值滤波算法,该算法在硬件平台上实现实时处理功能.综合考虑,选择现场可编程门阵列(FPGA)作为硬件平台,采用硬件描述 ...

  3. c语言均值滤波步骤,关于中值滤波算法,以及C语言实现

    中值滤波是一种非线性的图像平滑方法,与均值滤波器以及其他线性滤波器相比,它能够很好地滤除脉冲噪声,同时又能够保护目标图像边缘.它是一种邻域运算, 类似于卷积,但计算的不是加权求和,而是把邻域中的像素按 ...

  4. 关于中值滤波算法,以及C语言实现(转)

    源:关于中值滤波算法,以及C语言实现 1.什么是中值滤波? 中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制 ...

  5. verilog中值滤波算法实现及仿真

    使用verilog语言实现中值滤波算法,并编写testbench进行仿真,产生波形图. 可以使用vivado.ISE.quartusII等软件均可. 对代码.测试代码.仿真结果分别进行截图,如下所示: ...

  6. 高效快速中值滤波算法c语言,快速中值滤波及c语言实现.docx

    . .. 快速中值滤波及c语言实现 学生姓名: 刘 勇 学 号: 6100410218 专业班级: 数媒101 [摘要]本文讨论了用c语言在微机上实现中值滤波及快速算法,在程序设计的过程中充分考虑到程 ...

  7. matlab中基于十字形窗口的滤波算法,#215;字形滤波窗口在Matlab自适应中值滤波算法中的应用 - 21ic中国电子网...

    由于种种原因,图像在生成.传输.变换等过程中往往会受到各种噪声的污染,从而导致图像质量退化.噪声信号的滤波是图像处理的基本任务之一,主要有线性滤波和非线性滤波两种方法.线性滤波方法一般具有低通特性,而 ...

  8. Python扩展库scipy中值滤波算法的应用

    中值滤波是数字信号处理.数字图像处理中常用的预处理技术,特点是将信号中每个值都替换为其邻域内的中值,即邻域内所有值排序后中间位置上的值.下面的代码演示了scipy库中signal模块的中值滤波算法的用 ...

  9. MATLAB自编自适应中值滤波算法

    代码原理: 在噪声密度不是很大的情况下(根据经验,噪声的出现的概率小于0.2),使用中值滤波的效果不错.但是当噪声出现的概率比较高时,原来的中值滤波算法就不是很有效了.只有增大滤波器窗口尺寸,尽管会使 ...

  10. OpenCV图像处理专栏九 | 基于直方图的快速中值滤波算法

    转载自:https://zhuanlan.zhihu.com/p/98092747  侵删 前言 这是OpenCV图像处理专栏的第9篇文章,主要介绍一个基于直方图的快速中值滤波算法,希望对大家有帮助. ...

最新文章

  1. redis主从复制、高可用和集群
  2. 学python以后是做什么工作-对话极客晨星:现在学Python 长大可以从事什么工作?...
  3. Geometers Anonymous Club CodeForces - 1195F (闵可夫斯基和)
  4. 【mysql】str_to_date()字符串转化为日期类型
  5. matlab和robotstudio,MATLAB与Robotstudio建立socket通信(初探)
  6. 一线大厂青睐的前端人,90%满足这3个条件
  7. xiao77论坛php,论坛
  8. 深圳蛇口人民医院办理健康证,免费体检,2017年后国家承担体检费用
  9. Netscaler 10.5 VPX与XenApp XenDesktop 集成配置系列之三enable StoreFront Remote Access
  10. Flutter获取assets中的图像
  11. 水利水电专业英语(2.5k行超全)
  12. 如何巧用Microsoft edge浏览器合并pdf文件
  13. 龙芯2F入手,点滴记录!
  14. Learning a Proposal Classifier for Multiple Object Tracking
  15. android调用微信视频电话,微信视频通话录屏如何操作
  16. stm32 火灾自动报警及联动控制源码_火灾自动报警与消防联动控制系统
  17. 化妆品电商供应链系统解决方案:美妆化妆品品牌供应链质量管理、产品定位
  18. 扩展log4j2日志归档功能预研
  19. 2023山东智慧养老展/中国适老科技展/智能看护设备展
  20. [Win10] 代理服务器出现问题或地址有误

热门文章

  1. java反编译luyten使用
  2. svn 回退到指定版本无法提交_svn回滚到指定版本
  3. 为什么说苏宁必买万达百货
  4. VINS_Fusion学习01——官方教程翻译解读
  5. 手眼标定,我的结果显示手和眼相距上千米!手眼标定结果准确率如何提高?
  6. 2022张宇考研基础30讲 第十讲 积分等式与积分不等式
  7. mysql8.0密码重置
  8. 当前最流行的Javaweb框架有哪些?
  9. SNMP(简单网络管理协议)
  10. 使用C#解压缩文件,缺失ZipArchive类