基于FPGA的均值滤波算法的实现

  前面实现了基于FPGA的彩色图像转灰度处理,减小了图像的体积,但是其中还是存在许多噪声,会影响图像的边缘检测,所以这一篇就要消除这些噪声,基于灰度图像进行图像的滤波处理,为图像的边缘检测做好夯实基础。

  椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素。椒盐噪声是一种因为信号脉冲强度引起的噪声,产生该噪声的算法也比较简单。

  均值滤波的方法将数据存储成3x3的矩阵,然后求这个矩阵。在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。

  如图所示,我们要进行均值滤波首先要生成一个3x3矩阵。算法运算窗口一般采用奇数点的邻域来计算中值,最常用的窗口有3X3和5X5模型。下面介绍3X3窗口的Verilog实现方法。

  (1)通过2个或者3个RAM的存储来实现3X3像素窗口;

  (2)通过2个或者3个FIFO的存储来实现3X3像素窗口;

  (3)通过2行或者3行Shift_RAM的存储来实现3X3像素窗口;

  要想用实现均值滤波和中值滤波,必须要先生成3x3阵列,在Altera系列里,可以用QuatusII调用IP核——shift_RAM,具体设置参数如图所示。

  如上图所示,其中shiftin是实时输入的数据,taps1x,taps2x输入数据的第二三行,当数据输入成一行三个时,自动跳到下一行,最终形成每行是三列的一个矩阵,用均值滤波和中值滤波的处理方法即可,这样基本是每一个目标都可以找到自己对应的一个3x3矩阵,最后进行处理。先进入IP核里面的是最开始的的数据,所以在读出的时候也是要放在第一行。

  关于shift_ram的更详细的解释可以查看我的另一篇博文:http://www.cnblogs.com/ninghechuan/p/6789399.html

  这学期做比赛用的是国产FPGA,开发软件是PDS,这个软件说实话比较简洁,快,里面也有shift_ram IP core,但是不能设置多行(一个IP只能存储一行),不过只要你理解了shift_ram的工作的原理,完全可以用几个来实现多行处理,我通过PDS开发套件调用两个shift_register IP核来生成3X3矩阵实现3X3像素窗口。shift_register IP核可定义数据宽度、移位的行数、每行的深度。这里我们需要8bit。640个数据每行,同事移位寄存2行即可。同时选择时钟使能端口clken。

 1 shift_ram_end u_shift_ram_end1
 2      (
 3       .din       (row3_data),
 4       .clk       (shift_clk_en),
 5       .rst       (~rst_n),
 6       .dout      (row2_data)
 7      );
 8
 9 shift_ram_end u_shift_ram_end2
10      (
11       .din       (row2_data),
12       .clk       (shift_clk_en),
13       .rst       (~rst_n),
14       .dout      (row1_data)
15      );

  如图所示,我们这里将行设置为8,场设置为4,所以可以明显的看到,当数据缓存到一行时,就会移位寄存到下一行,缓存两行后便会生成3X3矩阵。

  如图所示,比较缓存的第一行的数据在3x3矩阵中,占第一行,结果相同,显然是正确的。

  如图所示,第二行、第三行和最终生成的3x3矩阵作比较,结果显然是正确的。

 1 //wire     [32:0]     matrix_row1 = {matrix_p11, matrix_p12,matrix_p13};//just for test
 2 //wire     [32:0]    matrix_row2 = {matrix_p21, matrix_p22,matrix_p23};
 3 //wire     [32:0]    matrix_row3 = {matrix_p31, matrix_p32,matrix_p33};
 4 always @(posedge clk or negedge rst_n)
 5 begin
 6     if(!rst_n)begin
 7            {matrix_p11, matrix_p12, matrix_p13}  <= 33‘h0;
 8          {matrix_p21, matrix_p22, matrix_p23} <= 33‘h0;
 9          {matrix_p31, matrix_p32, matrix_p33} <= 33‘h0;
10     end
11     else if(read_frame_href)begin
12         if(read_frame_clken)begin//shift_RAM data read clock enbale
13             {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data};//1th shift input
14             {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data};//2th shift input
15             {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data};//3th shift input
16         end
17         else begin
18             {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13};
19             {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23};
20             {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33};
21             end
22     end
23     else begin
24            {matrix_p11, matrix_p12, matrix_p13}  <= 33‘h0;
25          {matrix_p21, matrix_p22, matrix_p23} <= 33‘h0;
26          {matrix_p31, matrix_p32, matrix_p33} <= 33‘h0;
27         end
28 end

3x3矩阵生成

1 assign post_img_Y = mean_value4[10:3];//求平均值除以8,向右移位3位

  如图所示,将3x3矩阵的中心像素的周围八个点求和,我们上面还是采取了流水线的设计方法,来增加吞吐量,然后再求平均值代替目标像素的值,从波形图上观察,计算的结果显然是正确的。这样便完成了均值滤波的仿真。

 1 //--------------------------------------------
 2 //Generate 8bit 3x3 matrix for video image processor
 3 //Image data has been processd
 4 wire             matrix_frame_vsync;    //Prepared Image data vsync valid signal
 5 wire             matrix_frame_href;    //Prepared Image data href vaild  signal
 6 wire             matrix_frame_clken;    //Prepared Image data output/capture enable clock
 7 wire     [7:0]     matrix_p11, matrix_p12, matrix_p13;//3x3 materix output
 8 wire     [7:0]    matrix_p21, matrix_p22, matrix_p23;
 9 wire     [7:0]    matrix_p31, matrix_p32, matrix_p33;
10
11 shift_RAM_3x3 u_shift_RAM_3x3
12 (
13     //global signals
14     .clk                                (clk),
15     .rst_n                                (rst_n),
16     //Image data prepred to be processd
17     .per_frame_vsync                    (per_frame_vsync),    //Prepared Image data vsync valid signal
18     .per_frame_href                        (per_frame_href),        //Prepared Image data href vaild  signal
19     .per_frame_clken                    (per_frame_clken),    //Prepared Image data output/capture enable clock
20     .per_img_Y                            (per_img_Y),            //Prepared Image brightness input
21
22     //Image data has been processd
23     .matrix_frame_vsync                    (matrix_frame_vsync),    //Prepared Image data vsync valid signal
24     .matrix_frame_href                    (matrix_frame_href),    //Prepared Image data href vaild  signal
25     .matrix_frame_clken                    (matrix_frame_clken),    //Prepared Image data output/capture enable clock
26     .matrix_p11                            (matrix_p11),
27     .matrix_p12                            (matrix_p12),
28     .matrix_p13                            (matrix_p13),    //3X3 Matrix output
29     .matrix_p21                            (matrix_p21),
30     .matrix_p22                            (matrix_p22),
31     .matrix_p23                            (matrix_p23),
32     .matrix_p31                            (matrix_p31),
33     .matrix_p32                            (matrix_p32),
34     .matrix_p33                            (matrix_p33)
35
36 );
37
38 //-----------------------------------------------------------------------
39 //step1
40 reg     [10:0]     mean_value1, mean_value2, mean_value3;
41 always @(posedge clk or negedge rst_n)
42 begin
43     if(!rst_n)begin
44         mean_value1 <= 11‘d0;
45         mean_value2 <= 11‘d0;
46         mean_value3 <= 11‘d0;
47     end
48     else begin
49         mean_value1 <= matrix_p11 + matrix_p12 + matrix_p13;
50         mean_value2 <= matrix_p21 + 11‘d0 + matrix_p23;
51         mean_value3 <= matrix_p31 + matrix_p32 + matrix_p33;
52     end
53 end
54
55 //step2
56 reg     [10:0]    mean_value4;
57 always @(posedge clk or negedge rst_n)
58 begin
59     if(!rst_n)
60         mean_value4 <= 11‘d0;
61     else
62         mean_value4 <= mean_value1 + mean_value2 + mean_value3;
63 end

对3x3矩阵求均值

  当然,最后为了保持时钟的同步性,将消耗的时钟延时输出。

 1 //------------------------------------------------------------
 2 //delay 2 clk
 3 reg     [1:0]     per_frame_clken_r;
 4 reg     [1:0]     per_frame_href_r;
 5 reg     [1:0]     per_frame_vsync_r;
 6
 7 always @(posedge clk or negedge rst_n)
 8 begin
 9     if(!rst_n)begin
10         per_frame_clken_r <= 2‘b0;
11         per_frame_href_r <= 2‘b0;
12         per_frame_vsync_r <= 2‘b0;
13     end
14     else begin
15         per_frame_clken_r <= {per_frame_clken_r[0], matrix_frame_clken};
16         per_frame_href_r <= {per_frame_href_r[0], matrix_frame_href};
17         per_frame_vsync_r <= {per_frame_vsync_r[0], matrix_frame_vsync};
18     end
19 end
20
21 assign post_frame_vsync = per_frame_vsync_r[1];
22 assign post_frame_href  = per_frame_href_r[1];
23 assign post_frame_clken = per_frame_clken_r[1];

保持时钟的同步性

  图上为灰度图像,图下为均值滤波后的图像,可以看出滤波后的图像有一些模糊,这是因为均值滤波就是将图像做平滑处理,像素值高的像素会被拉低,像素值低像素会被拉高,趋向于一个平均值,所以图像会变模糊一些。这样基于FPGA的均值滤波就完成了,下一篇我会发布基于FPGA的中值滤波处理,并且比较这两种滤波方式的优劣,最终选取较好的一种滤波方式进行图像边缘检测处理。

转载请注明出处:NingHeChuan(宁河川)

个人微信订阅号:NingHeChuan

如果你想及时收到个人撰写的博文推送,可以扫描左边二维码(或者长按识别二维码)关注个人微信订阅号

知乎ID:NingHeChuan

微博ID:NingHeChuan

原文地址:http://www.cnblogs.com/ninghechuan/p/6984705.html

时间: 2024-12-27 18:33:01

基于FPGA的均值滤波算法的实现的相关文章

基于FPGA的均值滤波算法实现

我们为了实现动态图像的滤波算法,用串口发送图像数据到FPGA开发板,经FPGA进行图像处理算法后,动态显示到VGA显示屏上,前面我们把硬件平台已经搭建完成了,后面我们将利用这个硬件基础平台上来实现基于FPGA的一系列图像处理基础算法. 椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素.椒盐噪声是一种因为信号脉冲强度引起的噪声,产生清楚该噪声的算法也比较简单. 均值滤波的方法将数据存储成3x3的矩阵

基于暗通道去雾算法的实现与优化(二)opencv在pc上的实现

上一篇中,学习了何的论文中的去雾方法,这一篇中,我按照何的论文思路借助opencv 2.4.10 进行了实现,效果的确很好,就是耗时太多了,效果见下图:蓝色圆圈代表大气光值的取值点. 突然发现上一篇中忘了介绍大气光值A的求解了,论文中是这样做的: 1.首先取暗通道图中最亮的千分之一的像素点. 2.根据这些像素点的位置在原图中搜索一个最亮的点,这个点的强度(intensity)就是我们要求的A啦. 论文作者何认为这样做的好处就是避免了原图中比较亮的物体作为A的值,比如图片中的白色的汽车,如果从原图

基于 OpenMP 的奇偶排序算法的实现

代码: #include <omp.h> #include <iostream> #include <cstdlib> #include <ctime> using namespace std; const int NUM = 8000; const int MAX = 1000000; const int MIN = 0; const int NUM_THREADS = 8; int arr[NUM]; int main() { cout <<

基于FPGA的腐蚀膨胀算法实现

本篇文章我要写的是基于的腐蚀膨胀算法实现,腐蚀膨胀是形态学图像处理的基础,,腐蚀在二值图像的基础上做"收缩"或"细化"操作,膨胀在二值图像的基础上做"加长"或"变粗"的操作.那么什么是二值图像呢?把一幅图片看做成一个二维的数组,那么二值图像是一个只有0和1的逻辑数组,我们前面Sobel边缘检测后的图像输出边缘效果,设置个阈值,大于阈值输出为1,小于阈值输出为0,最后输出就是一幅二维图像了. 上一篇我是直接用MATLAB处理后的

基于FPGA的Sobel边缘检测的实现

前面我们实现了使用PC端上位机串口发送图像数据到VGA显示,通过MATLAB处理的图像数据直接是灰度图像,后面我们在此基础上修改,从而实现,基于FPGA的动态图片的Sobel边缘检测.中值滤波.Canny算子边缘检测.腐蚀和膨胀等.那么这篇文章我们将来实现基于FPGA的Sobel边缘检测. 图像边缘:简言之,边缘就是图像灰度值突变的地方,亦即图像在该部分的像素值变化速度非常之快,这就好比在坐标轴上一条曲线有刚开始的平滑突然来个大转弯,在变化出的导数非常大. Sobel算子主要用作边缘检测,在技术

基于FPGA的音频信号的FIR滤波(Matlab+Modelsim验证)

1 设计内容 本设计是基于FPGA的音频信号FIR低通滤波,根据要求,采用Matlab对WAV音频文件进行读取和添加噪声信号.FFT分析.FIR滤波处理,并分析滤波的效果.通过Matlab的分析验证滤波效果后,将叠加噪声信号的音频信号输出到txt文件里.然后使用Matlab语言编写滤波器模块和测试模块,通过Modelsim软件读取txt文件的数据,将数据送入滤波模块,最后将滤波的结果输出到txt文件里,最后用Matlab将处理的结果从txt文件读出.显示.FFT分析用Verilog设计的FIR滤

基于数组二分查找算法的实现

基于数组二分查找算法的实现 二分查找 查找 算法 赵振江 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功

基于思岚A1激光雷达+OpenGL+VS2017的Ramer-Douglas-Peucker算法的实现

时隔两年 又借到了之前的那个激光雷达,最老版本的思岚A1,甚至不支持新的固件,并且转接板也不见了,看了下淘宝店卖¥80,但是官方提供了一个基于STM32的实现方式,于是我估摸着这个转接板只是一个普通的USB-TTL转接板,那我就用340搭一个试试吧 根据官方的datasheet,电机可以5V供电,核心也是5V,电机使能是VMOTO电压,即5V,因此将三个接口焊到一起,两个地焊到一起,然后剩下一组TXRX,因此七个接口变成四个接口了,正好能接上340,于是插上电试了试,当然...没有那么顺利,报错

图像平滑技术之盒滤波、均值滤波、中值滤波、高斯滤波、双边滤波的原理概要及OpenCV代码实现

图像平滑是指直接对源图像的每个像素数据做邻域运算以达到平滑图像的目的.实质上主要就是通达卷积核算子实现的,卷积核算子的相关知识大家可以参考我写的博文http://blog.csdn.net/wenhao_ir/article/details/51691410 图像平滑也称为模糊或滤波,是图像处理中常用的技术之一,进行平滑处理时需要用到滤波器核(其实就是卷积核算子),根据滤波器核函数来实现不同的滤波技术.下面介绍几种 常用的图像平滑方法的大概原理及OpenCV下的实现代码. 一.盒滤波(均值滤波)