FPGA 实现图像的3*3算子模板

一、为什么要使用算子模板

        图像处理中,我们经常需要对采集到的图像进行滤波操作,进行滤波操作我们需要用一个滑动模板,在整幅图像中进行滑窗处理。普通的滑窗有3x3、5x5、7x7等形式。本文主要讲述一种简单的3x3模板的概念以及如何用Verilog实现。

二、3x3模板的原理

图一

         如图一所示,我们把这个表格想象成一个10x10的图片,每一个小方块就是一个像素点。当选择简单的3x3模板进行处理时,如图二所示。

图二

        图中蓝色的部分就是我们所使用的3x3滑动窗口,对整幅图片进行滑窗操作。同时我们也看到了,当我们需要处理边界信息的时候,我们的简单滑窗是无法进行运算的,这也是简单滑窗操作的一个缺点,想要改进这个缺点,我们需要对边界进行填充处理,填充处理的方法有很多,我们本期主要介绍滑窗模板的使用,这里对边界填充问题就不做过多的说明了。

三、Verilog实现

       在实际的图像处理中,一般都会通过FIFO进行图像数据的缓存。使用3x3模板,我们至少需要两个深度大于图像行个数的FIFO,通过首尾相连的方式来缓存两行数据。等到第三行来的时候,同时输出三行数据。但这里需要注意,在3x3模板模板中,第二个FIFO缓存的是第一行数据,第一个FIFO缓存的是第二行的数据。

       话不多说上代码,

`timescale 1ns / 1ps
`define TEMPLATE_3X3

module image_template
(
	input   wire				i_clk,
	input   wire				i_rst_n,

	input	wire				i_en,
	input	wire [7:0]			i_data,

	output	reg 				o_en,
	`ifdef TEMPLATE_3X3
	output  reg [7:0]			o_temp_11,
	output  reg [7:0]			o_temp_12,
	output  reg [7:0]			o_temp_13,	
	output  reg [7:0]			o_temp_21,
	output  reg [7:0]			o_temp_22,
	output  reg [7:0]			o_temp_23,		
	output  reg [7:0]			o_temp_31,
	output  reg [7:0]			o_temp_32,
	output  reg [7:0]			o_temp_33
	`endif
);
parameter  H_ACTIVE = 1280;                              
parameter  V_ACTIVE = 720;  

reg  [10:0]	h_cnt;
reg  [10:0]	v_cnt;

wire [7:0]	fifo_1_in;
wire 		fifo_1_wr_en;
wire 		fifo_1_rd_en;
wire [7:0]	fifo_1_out;

wire [7:0]	fifo_2_in;
wire 		fifo_2_wr_en;
wire 		fifo_2_rd_en;
wire [7:0]	fifo_2_out;



always@(posedge i_clk or negedge i_rst_n) 
begin
    if(!i_rst_n)
	begin
        h_cnt <= 11'd0;
    end
    else if(i_en)
	begin
		if(h_cnt == H_ACTIVE - 1'b1)
			h_cnt <= 11'd0;
		else 
			h_cnt <= h_cnt + 11'd1;
    end
end

always@(posedge i_clk or negedge i_rst_n) 
begin
    if(!i_rst_n)
	begin
        v_cnt <= 11'd0;
    end
    else if(h_cnt == H_ACTIVE - 1'b1)
	begin
		if(v_cnt == V_ACTIVE - 1'b1)
			v_cnt <= 11'd0;
		else 
			v_cnt <= v_cnt + 11'd1;
    end
end


assign fifo_1_in	= i_data;
assign fifo_1_wr_en	= (v_cnt < V_ACTIVE - 1) ? i_en : 1'b0;
assign fifo_1_rd_en	= (v_cnt > 0) ? i_en : 1'b0;

assign fifo_2_in	= fifo_1_out;
assign fifo_2_wr_en	= fifo_1_rd_en;
assign fifo_2_rd_en	= (v_cnt > 1) ? i_en : 1'b0;


fifo_generator_0 u_fifo_1(
	.clk		(i_clk			), 
	.srst		(!i_rst_n		), 
	.din 		(fifo_1_in		),
	.wr_en		(fifo_1_wr_en	),
	.rd_en		(fifo_1_rd_en	),
	.dout 		(fifo_1_out		),
	.full 		(				),
	.empty		(				), 
	.data_count	(				)
);

fifo_generator_0 u_fifo_2(
	.clk		(i_clk			), 
	.srst		(!i_rst_n		), 
	.din 		(fifo_2_in		),
	.wr_en		(fifo_2_wr_en	),
	.rd_en		(fifo_2_rd_en	),
	.dout 		(fifo_2_out		),  
	.full 		(				),
	.empty		(				), 
	.data_count	(				)
);

`ifdef TEMPLATE_3X3
always@(posedge i_clk or negedge i_rst_n) 
begin
    if(!i_rst_n) 
	begin
		o_temp_11	<= 8'd0;
		o_temp_12	<= 8'd0;
		o_temp_13	<= 8'd0;
		
		o_temp_21	<= 8'd0;
		o_temp_22	<= 8'd0;
		o_temp_23	<= 8'd0;
		
		o_temp_31	<= 8'd0;
		o_temp_32	<= 8'd0;
		o_temp_33	<= 8'd0;
    end
	else
	begin
		o_temp_11	<= o_temp_12;
		o_temp_12	<= o_temp_13;
		o_temp_13	<= fifo_2_out;
		
		o_temp_21	<= o_temp_22;
		o_temp_22	<= o_temp_23;
		o_temp_23	<= fifo_1_out;
		
		o_temp_31	<= o_temp_32;
		o_temp_32	<= o_temp_33;
		o_temp_33	<= i_data;	
	end
end

always@(posedge i_clk or negedge i_rst_n) 
begin
    if(!i_rst_n) 
	begin
		o_en	<= 1'b0;
    end
	else if((v_cnt > 1)&&(h_cnt > 1))
	begin
		o_en	<= i_en;
	end
	else
	begin
		o_en	<= 1'b0;
	end	
end
`endif

endmodule

仿真结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值