基于EBAZ4205矿板的图像处理:05均值滤波算法
项目全部文件已经上传,是免费的
先看效果
可以明显看到图像变糊了,这就是均值滤波的特点,将噪声均摊到每个点上的同时,也会让图像丢失细节。
算法讲解
均值滤波,简直是太简单了,就是用一个滑动窗口的所有像素点的均值代替该滑动窗口的中心像素点的的像素值。
算法的FPGA部署
算法本身很简单,但是这里的实现思想却很重要!!
均值计算,自然少不了除法,计算均值就是sum/N,但是,对于FPGA而言,涉及到浮点数的除法预算很耗时,所以这里最推荐的做法就是将分子和分母都整数倍扩大,让sum乘上一个很大的数,然后移位除法,这样就实现了用整型运算替代了浮点数运算,大幅节约了运算耗时,和运算资源。
所以这里的做法是sumx3641,然后右移15位(移位除法),再加上sumx3641的第14位(四舍五入)。
block design
其实和我的上一篇是一样的,只有video_procress 模块里面代码不一样
项目代码
video_process 模块
module video_processor(
(* X_INTERFACE_IGNORE = "true" *) input frame_clk, //cmos 像素时钟
(* X_INTERFACE_IGNORE = "true" *) input frame_rst_n,
//预处理图像
(* X_INTERFACE_IGNORE = "true" *) input pre_vsync, //预处理图像场同步信号
(* X_INTERFACE_IGNORE = "true" *) input [23:0] pre_data, //预处理图像数据
(* X_INTERFACE_IGNORE = "true" *) input pre_href, //预处理图像数据有效信号
(* X_INTERFACE_IGNORE = "true" *) input pre_frame_ce, //预处理图像时钟使能信号
//阈值控制
(* X_INTERFACE_IGNORE = "true" *) input [7:0 ] loc_bin_thresh_coefficient, //来自PS端的局部二值化阈值系数
//处理后图像
(* X_INTERFACE_IGNORE = "true" *) output pos_vsync, //处理后图像场同步信号
(* X_INTERFACE_IGNORE = "true" *) output [23:0] pos_data, //处理后图像数据
(* X_INTERFACE_IGNORE = "true" *) output pos_href, //处理后图像数据有效信号
(* X_INTERFACE_IGNORE = "true" *) output pos_frame_ce //处理后图像时钟使能信号
);
//wire define
wire [7:0] gray_data ;
wire gray_vsync;
wire gray_frame_ce;
wire gray_href;
//*****************************************************
//** main code
//*****************************************************
//rgb转ycbcr模块
rgb2gray u_rgb2gray(
.cmos_frame_clk (frame_clk ),
.cmos_rstn (frame_rst_n ),//同步复位
.cmos_frame_vsync (pre_vsync ),
.cmos_frame_data (pre_data ),
.cmos_frame_href (pre_href ),
.cmos_frame_ce (pre_frame_ce ),
.dataout_frame_vsync(gray_vsync ),
.dataout_frame_data (gray_data ),
.dataout_frame_href (gray_href ),
.dataout_frame_ce (gray_frame_ce )
);
//wire define
wire matrix_frame_vsync;
wire matrix_frame_href;
wire matrix_frame_ce;
wire [7:0] matrix_p11; //3X3 矩阵数据
wire [7:0] matrix_p12;
wire [7:0] matrix_p13;
wire [7:0] matrix_p21;
wire [7:0] matrix_p22;
wire [7:0] matrix_p23;
wire [7:0] matrix_p31;
wire [7:0] matrix_p32;
wire [7:0] matrix_p33;
VIP_matrix_generate_3x3_8bit u_VIP_matrix_generate_3x3_8bit(
.clk (frame_clk ),
.rst_n (frame_rst_n ),
.per_frame_vsync (gray_vsync ),
.per_frame_href (gray_href ),
.per_frame_ce (gray_frame_ce ),
.per_img_Y (gray_data ),
//输出3x3矩阵
.matrix_frame_vsync (matrix_frame_vsync ),
.matrix_frame_href (matrix_frame_href ),
.matrix_frame_ce (matrix_frame_ce ),
.matrix_p11 (matrix_p11),
.matrix_p12 (matrix_p12),
.matrix_p13 (matrix_p13),
.matrix_p21 (matrix_p21),
.matrix_p22 (matrix_p22),
.matrix_p23 (matrix_p23),
.matrix_p31 (matrix_p31),
.matrix_p32 (matrix_p32),
.matrix_p33 (matrix_p33)
);
avg_filter u_avg_filter(
.clk (frame_clk ),
.rst_n (frame_rst_n ),
.matrix_img_vsync (matrix_frame_vsync ),
.matrix_img_href (matrix_frame_href ),
.matrix_frame_ce (matrix_frame_ce ),
.matrix_p11 (matrix_p11 ),
.matrix_p12 (matrix_p12 ),
.matrix_p13 (matrix_p13 ),
.matrix_p21 (matrix_p21 ),
.matrix_p22 (matrix_p22 ),
.matrix_p23 (matrix_p23 ),
.matrix_p31 (matrix_p31 ),
.matrix_p32 (matrix_p32 ),
.matrix_p33 (matrix_p33 ),
.dataout_vsync (pos_vsync ),
.dataout_href (pos_href ),
.dataout_gray (pos_data ),
.dataout_frame_ce (pos_frame_ce ));
endmodule
均值滤波模块
`timescale 1ns / 1ps
//作者:抢公主的大魔王
//日期:24.5.15
module avg_filter(
(* X_INTERFACE_IGNORE = "true" *) input wire clk ,
(* X_INTERFACE_IGNORE = "true" *) input wire rst_n ,
(* X_INTERFACE_IGNORE = "true" *) input wire matrix_img_vsync,
(* X_INTERFACE_IGNORE = "true" *) input wire matrix_img_href,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p11,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p12,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p13,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p21,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p22,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p23,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p31,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p32,
(* X_INTERFACE_IGNORE = "true" *) input wire [7:0] matrix_p33,
(* X_INTERFACE_IGNORE = "true" *) input wire matrix_frame_ce,
(* X_INTERFACE_IGNORE = "true" *) output reg dataout_vsync , // processed Image data vsync valid signal
(* X_INTERFACE_IGNORE = "true" *) output reg dataout_href , // processed Image data href vaild signal
(* X_INTERFACE_IGNORE = "true" *) output reg [23:0] dataout_gray , // processed Image brightness output
(* X_INTERFACE_IGNORE = "true" *) output reg dataout_frame_ce
);
//----------------------------------------------------------------------
// calc sum of [p11,p12,p13;p21,p22,p23;p31,p32,p33]
reg [ 9:0] data_sum1;
reg [ 9:0] data_sum2;
reg [ 9:0] data_sum3;
reg [11:0] data_sum;
always @(posedge clk)
begin
data_sum1 <= matrix_p11 + matrix_p12 + matrix_p13;
data_sum2 <= matrix_p21 + matrix_p22 + matrix_p23;
data_sum3 <= matrix_p31 + matrix_p32 + matrix_p33;
data_sum <= data_sum1 + data_sum2 + data_sum3;
end
//----------------------------------------------------------------------
// avg_data = round(data_sum/9.0) -> avg_data = round(data_sum*3641 >> 15)
reg [22:0] data_mult;
always @(posedge clk)
begin
data_mult <= data_sum * 12'd3641;
end
reg [7:0] avg_data;
always @(posedge clk)
begin
avg_data <= data_mult[22:15] + data_mult[14];
end
//----------------------------------------------------------------------
// lag 4 clocks signal sync
reg [3:0] matrix_img_vsync_r1;
reg [3:0] matrix_img_href_r1;
reg [3:0] matrix_frame_ce_r1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
matrix_img_vsync_r1 <= 4'b0;
matrix_img_href_r1 <= 4'b0;
matrix_frame_ce_r1 <= 4'b0;
end
else
begin
matrix_img_vsync_r1 <= {matrix_img_vsync_r1[2:0],matrix_img_vsync};
matrix_img_href_r1 <= {matrix_img_href_r1[2:0],matrix_img_href};
matrix_frame_ce_r1 <= {matrix_frame_ce_r1[2:0],matrix_frame_ce};
end
end
reg [7:0] matrix_p22_r1 [0:3];
always @(posedge clk)
begin
matrix_p22_r1[0] <= matrix_p22;
matrix_p22_r1[1] <= matrix_p22_r1[0];
matrix_p22_r1[2] <= matrix_p22_r1[1];
matrix_p22_r1[3] <= matrix_p22_r1[2];
end
//----------------------------------------------------------------------
// result output
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
dataout_gray <= 'd0;
else
dataout_gray <= {3{avg_data}};
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
dataout_vsync <= 1'b0;
dataout_href <= 1'b0;
dataout_frame_ce <= 1'b0;
end
else
begin
dataout_vsync <= matrix_img_vsync_r1[3];
dataout_href <= matrix_img_href_r1[3];
dataout_frame_ce <= matrix_frame_ce_r1[3];
end
end
endmodule