图像处理领域的线性滤波器主要包括均值滤波和高斯滤波等平滑滤波器,此外,还有Sobel算子、Laplas算子和梯度运算等锐化滤波器。线性滤波通常的处理方法是利用一个指定尺寸的掩模(mask)对图像进行卷积,通常,这个掩模(mask)也可以称为滤波器(filter)、 核(kernel)、模板(template)和窗(window) 等。这里给出线性滤波器的定义如下:设r为处理窗口的半径,f(i,j) 为窗口内模板的灰度值, I(x, y)为输入像素值,g(x,y)
为输出像素值,则有如下定义:
令g(x,y)滑过整幅图像,即对整幅图像做一个 卷积处理,就得到最后的滤波结果。由卷积定理可以得到,在频域将模板直接与图像进行像素相乘也可以达到相同的目的。
均值滤波是典型的线性滤波算法,主要方法为邻域平均法,即用一个图像区域的各个像素的平均值来代替原图像的各个像素值。均值滤波的主要作用是减小图像灰度值的“尖锐”变化从而达到减小噪声的目的。但是,由于图像边缘在一般情况下也是由图像灰度尖锐化引起的,因此,均值滤波也存在边缘模糊的问题。
一、理论分析
一般来说, 图像具有局部连续性质,即相邻像素的数值相近,而噪声的存在使得在噪声点处产生灰度跳跃,但- -般我们可以合理地假设偶尔出现的噪声影响并没有改变图像局部连续的性质,例如下面的局部图像 f _sub,灰色底纹标识的为噪声点,在图像中表现为亮区中的 2 个暗点:
对 f 用 3X3 的平均模板进行平滑滤波后,得到的平滑后图像 g_ sub:
显然,通过平滑滤波原局部图像 f_sub 中噪声点的灰度值得到了有效修正,像这样将每一个点用周围点的平均替代从而达到减少噪声影响的过程就称为平滑或模糊。随着模板的增大,滤波过程在平滑更多噪声的同时也使得图像变得越来越模糊,这是由平均模板的工作机理决定的。当图像细节与滤波器模板大小相近时,图像细节就会受到比较大的影响,尤其当它们的灰度值比较接近时,混合效应导致的图像模糊会更明显。随着模板地进一步增大,很多细节都会被当作噪声平滑掉。因此,我们在确定模板尺寸时应仔细考虑要滤除的噪声点的大小,有针对性地进行滤波。
以 3x3 为例,均值滤波说白了就是将图像数据生成3x3的矩阵,对这九个数求个平均值代替中间的那个数。在FPGA中我们为了简便运算只将目标像素周围八个点求和然后除以8,取代中间像素点。
二、MATLAB实现
clc; clear all; close all; RGB = imread('flower.bmp'); %读取图片 imgn = imnoise(RGB,'salt & pepper',0.05); %椒盐密度0.05 gray = im2double(rgb2gray(imgn)); %灰度图 [ROW,COL, DIM] = size(gray); %得到图像行列数 %-------------------------------------------------------------------------- % Mean Filter 均值滤波 %-------------------------------------------------------------------------- Mean_Img = zeros(ROW,COL); for r = 2:1:ROW-1 for c = 2:1:COL-1 Mean_Img(r,c) = (gray(r-1, c-1) + gray(r-1, c) + gray(r-1, c+1) + gray(r, c-1) + gray(r, c) + gray(r, c+1) + gray(r+1, c-1) + gray(r+1, c) + gray(r+1, c+1)) / 9; end end %-------------------------------------------------------------------------- % Show Image %-------------------------------------------------------------------------- subplot(2,2,1); imshow(RGB); title('原图'); subplot(2,2,2); imshow(imgn); title('椒盐噪声'); subplot(2,2,3); imshow(gray); title('灰度图'); subplot(2,2,4); imshow(Mean_Img); title('均值滤波'); % 由实验可知: % 1、均值滤波会使得图像模糊,其实是做了平滑处理,像素值高的会被拉低,像素值低的会被拉高,趋向于一个平均值。 % 2、椒盐噪声就是黑白噪声,均值滤波对椒盐噪声基本无作用,必须使用中值滤波才行。
点击运行,得到如下结果:
由结果看出:均值滤波对略去了部分噪声,但不如上篇的中值滤波效果好。中值滤波后,图片变的模糊,其实是做了平滑处理,像素值高的会被拉低,像素值低的会被拉高,趋向于一个平均值。
三、FPGA实现
1、形成3x3矩阵
这个在前面的博客花了3篇来解释,就不多说了,我把3x3矩阵的代码用一个专门的 .v 文件写好,这里直接调用即可。输入是灰度数据,即 YCbCr格式中的 8bit Y分量,输出是矩阵数据。耗费 1 个时钟周期。
//========================================================================== //== matrix_3x3_8bit,生成3x3矩阵,输入和使能需对齐,耗费1clk //========================================================================== //--------------------------------------------------- 矩阵顺序 // {matrix_11, matrix_12, matrix_13} // {matrix_21, matrix_22, matrix_23} // {matrix_31, matrix_32, matrix_33} //--------------------------------------------------- 模块例化 matrix_3x3_8bit #( .COL (480 ), .ROW (272 ) ) u_matrix_3x3_8bit ( .clk (clk ), .rst_n (rst_n ), .din_vld (Y_de ), .din (Y_data ), .matrix_11 (matrix_11 ), .matrix_12 (matrix_12 ), .matrix_13 (matrix_13 ), .matrix_21 (matrix_21 ), .matrix_22 (matrix_22 ), .matrix_23 (matrix_23 ), .matrix_31 (matrix_31 ), .matrix_32 (matrix_32 ), .matrix_33 (matrix_33 ) );
2、均值滤波
本来的均值滤波是周围8个像素包括自己共9个,相加除以9,FPGA不适合做除法,因此改成只取周围8个像素,相加除以8,即右移3位,即取高8位。共耗费 2 个时钟周期。
//mean ---------------------------------------------- reg [10:0] mean1 ; reg [10:0] mean2 ; reg [10:0] mean3 ; reg [10:0] mean4 ; //========================================================================== //== 均值滤波,耗费2clk //========================================================================== //clk 1 //--------------------------------------------------- always @(posedge clk or negedge rst_n) begin if(!rst_n) begin mean1 <= 'd0; mean2 <= 'd0; mean3 <= 'd0; end else begin mean1 <= matrix_11 + matrix_12 + matrix_13; mean2 <= matrix_21 + + matrix_23; mean3 <= matrix_31 + matrix_32 + matrix_33; end end //clk 2 //--------------------------------------------------- always@(posedge clk or negedge rst_n) begin if(!rst_n) mean4 <= 'd0; else mean4 <= mean1 + mean2 + mean3; end assign mean_data = mean4[10:3];
3、信号同步
形成 3x3 矩阵耗费 1clk,均值滤波耗费 2clk,因此行场和使能信号都需要延迟3拍。
//========================================================================== //== 信号同步 //========================================================================== always @(posedge clk or negedge rst_n) begin if(!rst_n) begin Y_de_r <= 3'b0; Y_hsync_r <= 3'b0; Y_vsync_r <= 3'b0; end else begin Y_de_r <= {Y_de_r[1:0], Y_de}; Y_hsync_r <= {Y_hsync_r[1:0], Y_hsync}; Y_vsync_r <= {Y_vsync_r[1:0], Y_vsync}; end end assign mean_de = Y_de_r[2]; assign mean_hsync = Y_hsync_r[2]; assign mean_vsync = Y_vsync_r[2];
四、上板验证
灰度图:
均值滤波后:
从实验结果看出,图片变得模糊了,其实是平滑了,实验成功。
我的板子坏了,出现一些不该有的横条,如果是好的板子则没有这些鬼东西。
[1] OpenS Lee:FPGA开源工作室(公众号)
[2] CrazyBingo:基于VIP_Board Mini的FPGA视频图像算法(HDL-VIP)开发教程-V1.6
[3] NingHechuan:FPGA图像处理教程