7.3*3卷积核生成

1.卷积核

  在数字图像处理中的各种边沿检测、滤波、腐蚀膨胀等操作都离不开卷积核的生成。下面介绍如何生成各种3X3的卷积核。为后面的数字图像操作打下基础。
  由于图像经过卷积操作后会减少两行两列,因此在生成卷积核的时候一般会对图像进行填充,填充的方式有加0,加1和复制边界三种方法。
  有的图像处理会在卷积完成之后才对图像进行填充,有的会在卷积前填充。我个人比较喜欢在卷积前填充,对于填充的方式,如果在卷积后填充,边沿可能会产生白边或者黑边,我个人不大喜欢,所以后续的图像处理一律采用卷积前填充以及边沿复制的填充方式来做3X3矩阵。由于拜尔转RGB等一些操作不需要填充,所以也会使用无填充的3X3矩阵生成模块。
  本文将会构建边沿填充的3X3矩阵生成模块和一个边沿不填充的3X3矩阵模块。其中边沿填充模块可以选择填充0或者1或者边沿复制三种填充方式。
在这里插入图片描述
在这里插入图片描述

2.边沿填充模式卷积核生成

2.1 具有边沿填充的卷积代码

  首先生成一个FWFT的FIFO模块,然后编写下面的卷积核模块

module 	padding_matrix #(
	parameter 	COL 	= 	1920 	 	,
	parameter 	ROW 	= 	1080 	 	,
	parameter 	PADDING = 	0 			
)(
 	input 	wire 			clk 		,
 	input 	wire 			rst_n 		,

 	input 	wire 	[7:0] 	data 		,
 	input 	wire 	 		data_de 	,
	input 	wire    [1:0] 	padding     , 

 	output 	wire  			matrix_de 	,
 	output 	reg 	[7:0] 	matrix11 	,
 	output 	reg 	[7:0] 	matrix12 	,
 	output 	reg 	[7:0] 	matrix13 	,
 	output 	reg 	[7:0] 	matrix21 	,
 	output 	reg 	[7:0] 	matrix22 	,
 	output 	reg 	[7:0] 	matrix23 	,
 	output 	reg 	[7:0] 	matrix31 	,
 	output 	reg 	[7:0] 	matrix32 	,
 	output 	reg 	[7:0] 	matrix33 	
);

reg 	[1:0] 	 data_de_r 	;
reg 	[7:0] 	 data_r1 	;
reg 	[7:0] 	 data_r2 	;

reg 	[15:0] 	 col_cnt 	;
reg 	[15:0] 	 row_cnt 	;	

reg 			data_valid 	;
reg 	[4:0]	data_valid_r;
reg 			fake_data_valid;

wire 	[7:0] 	row1_data 	;
wire 	[7:0] 	row2_data 	;
reg 	[7:0] 	row3_data 	;

always @(posedge clk )begin
	data_de_r <= {data_de_r[1:0],data_de};
	data_valid_r 	<= 	{data_valid_r[3:0],data_valid};
	data_r1 	<= 	data 		;
end
wire 	pos_data_de;
assign 	pos_data_de = {data_de_r[0],data_de} == 2'b01;

always @(posedge clk or negedge rst_n)begin
	if(rst_n == 0)begin
		col_cnt 	<= 0;
	end
	else if(col_cnt == COL + 1)begin
		col_cnt 	<= 0;
	end
	else if(data_valid || fake_data_valid)begin
		col_cnt 	<= col_cnt + 1;
	end
end

always @(posedge clk or negedge rst_n)begin
	if(rst_n == 0)begin
		row_cnt 	<= 0;
	end
	else if(col_cnt == COL + 1 && row_cnt == ROW )begin
		row_cnt	 	<= 0;
	end
	else if(col_cnt == COL + 1)begin
		row_cnt 	<= row_cnt + 1;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 0) begin		
		fake_data_valid 	<= 0;
	end
	else if (data_valid_r[4] == 0 && row_cnt == ROW && col_cnt <= COL  ) begin
		fake_data_valid 	<= 1;
	end
	else begin
		fake_data_valid 	<= 	0;
	end
end

always @(posedge clk or negedge rst_n)begin
	if(rst_n == 0)begin
		row3_data 	<= 0;
	end
	else if(col_cnt == 0 && pos_data_de && padding == 0)begin
		row3_data 	<= 0 ;
	end
	else if(col_cnt == 0 && pos_data_de && padding == 1)begin
		row3_data 	<= 8'hFF ;
	end
	else if(col_cnt == 0 && pos_data_de)begin
		row3_data 	<= data ;
	end
	else if(col_cnt == COL && data_de_r[1] && padding == 0)begin
		row3_data 	<= 0;
	end
	else if(col_cnt == COL && data_de_r[1] && padding == 1)begin
		row3_data 	<= 8'hFF;
	end
	else if(col_cnt == COL && data_de_r[1])begin
		row3_data 	<= row3_data;
	end
	else begin
		row3_data 	<= data_r1;
	end
end

always@(posedge clk or negedge rst_n)begin
	if(rst_n == 0)begin
		data_valid <= 0;
	end
	else if(data_de || data_de_r[1])begin
		data_valid <= 1'b1;
	end
	else begin
		data_valid <= 1'b0;
	end
end

wire 			rd_en 	;	

fifo_matrix_buf u1_fifo_matrix_buf (
	.rst 		(!rst_n		),  
	.wr_clk 	(clk  	 	),  
	.rd_clk 	(clk 	 	),  
	.din 		(row2_data 	),  
	.wr_en 		(data_valid ),  
	.rd_en 		(rd_en 	 	),  
	.dout 		(row1_data 	),  
	.full 		( 	 		),  
	.empty 		( 	 		)   
);

fifo_matrix_buf u2_fifo_matrix_buf (
	.rst 		(!rst_n		),  
	.wr_clk 	(clk  	 	),  
	.rd_clk 	(clk 	 	),  
	.din 		(row3_data 	),  
	.wr_en 		(data_valid ),  
	.rd_en 		(rd_en 		),  
	.dout 		(row2_data 	), 
	.full 		(   		),  
	.empty 		(    		)   
);

assign rd_en = (row_cnt > 0 & (data_valid | fake_data_valid) )? 1'b1 : 1'b0;

always @(posedge clk or negedge rst_n)begin
	if(rst_n == 0)begin
		{matrix11,matrix12,matrix13} 	<= 	24'd0;
		{matrix21,matrix22,matrix23} 	<= 	24'd0;
		{matrix31,matrix32,matrix33} 	<= 	24'd0;
	end
	else if(rd_en)begin
 		if(row_cnt == 1)begin
			if (padding == 0) begin
				{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,  	   0};
				{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
				{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,row3_data};				
			end
			if (padding == 1) begin
				{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,    8'hFF};
				{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
				{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,row3_data};				
			end
			else begin
				{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,row2_data};
				{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
				{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,row3_data};				
			end
 		end	
 		else if (row_cnt == ROW) begin
			if (padding == 0) begin
				{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,row1_data};
				{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
				{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,        0};				
			end
			else if(padding == 1) begin
				{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,row1_data};
				{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
				{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,    8'hff};				
			end
			else begin
				{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,row1_data};
				{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
				{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,row2_data};				
			end			
 		end
 		else begin
			{matrix11,matrix12,matrix13} 	<= 	{matrix12,matrix13,row1_data};
			{matrix21,matrix22,matrix23} 	<= 	{matrix22,matrix23,row2_data};
			{matrix31,matrix32,matrix33} 	<= 	{matrix32,matrix33,row3_data};
 		end	
	end
end

reg 	[3:0] 	rd_en_r;
always @(posedge clk)begin
	rd_en_r 	<= 	{rd_en_r[2:0],rd_en};
end

assign 	matrix_de 	= 	rd_en_r[2] & rd_en_r[0] ;

endmodule 		

2.2 边沿填充的卷积核仿真代码

`timescale 1ns / 1ps

module img_gen
#(
 	parameter 	ACTIVE_IW 	= 	1920 	,
 	parameter 	ACTIVE_IH 	= 	1080 	,
 	parameter 	TOTAL_IW 	= 	2200 	,
 	parameter 	TOTAL_IH 	= 	1100 	,
 	parameter 	H_START 	= 	100 	,
 	parameter 	V_START 	= 	4 		 		
)(
	input 	wire 				clk 	,
	input 	wire 				rst_n 	,
	output 	reg 				vs 		,
	output 	reg  	 	 		de 		,
	output 	wire 	[7:0] 		data 	
);




reg 	[15:0] 	hcnt 	;
reg 	[15:0] 	vcnt 	;

reg 			h_de 	;
reg 			v_de  	;

reg  			index_de 	;
reg 	[31:0] 	index 	 	;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		hcnt <= 'd0;
	else if(hcnt == TOTAL_IW - 1)
		hcnt <= 'd0;
	else 
		hcnt <= hcnt + 1'b1;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		vcnt <= 'd0;
	else if(hcnt == TOTAL_IW - 1 && vcnt == TOTAL_IH - 1)
		vcnt <= 'd0;
	else if(hcnt == TOTAL_IW - 1)
		vcnt <= vcnt + 1'b1;
	else 
		vcnt <= vcnt;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		vs <= 'd0;
	else if(vcnt>=2)
		vs <= 1'b1;
	else 
		vs <= 1'b0;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		h_de <= 'd0;
	else if(hcnt >= H_START && hcnt < H_START + ACTIVE_IW)
		h_de <= 1'b1;
	else 
		h_de <= 1'b0;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		v_de <= 'd0;
	else if(vcnt >= V_START && vcnt < V_START + ACTIVE_IH)
		v_de <= 1'b1;
	else 
		v_de <= 1'b0;


always @(posedge clk or negedge rst_n)
	if(!rst_n)
		index_de <= 'd0;
	else if(h_de == 1'b1 && v_de == 1'b1)
		index_de <= 1'b1;
	else 
		index_de <= 1'b0;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		index <= 'd0;
	else if(index == ACTIVE_IW * ACTIVE_IH-1)
		index <= 0;
	else if(index_de == 1'b1)
		index <= index + 1;
	else 
		index <= index;

always @(posedge clk or negedge rst_n)
	if(!rst_n)
		de <= 'd0;
	else 
		de <= index_de;
assign 	data 	= index;
endmodule
`timescale 1ns / 1ps


module tb_matrix();

reg 	clk 	;
reg 	rst_n 	;

wire 	[7:0] 	data 	;
wire 			de  	;

wire 			vs  	;

wire 	[7:0] 	matrix11; 	
wire 	[7:0] 	matrix12; 	
wire 	[7:0] 	matrix13; 	
wire 	[7:0] 	matrix21; 	
wire 	[7:0] 	matrix22; 	
wire 	[7:0] 	matrix23; 	
wire 	[7:0] 	matrix31; 	
wire 	[7:0] 	matrix32; 	
wire 	[7:0] 	matrix33; 	

always #5 clk 	<= 	~clk;
initial 	begin
	clk 	<= 0;
	rst_n 	= 0;
	#2000
	rst_n 	= 1;
end

img_gen
#(
 	.ACTIVE_IW 	(5 	),
 	.ACTIVE_IH 	(5 	),
 	.TOTAL_IW 	(11 	),
 	.TOTAL_IH 	(11 	),
 	.H_START 	(4 	 	),
 	.V_START 	(4 	 	) 		
)u_img_gen(
	.clk 	 	(clk 	 	),
	.rst_n 	 	(rst_n 	 	),
	.vs 		(vs 		),
	.de 		(de 		),
	.data 	 	(data 	 	)
);

matrix #(
	.COL(5),
	.ROW(5)
)u_matrix(
 	.clk 	 	(clk 	 	),
 	.rst_n 	 	(rst_n 	 	),

 	.data 	 	(data 	 	),
 	.data_de  	(de 	  	),

 	.matrix11 	(matrix11 	),
 	.matrix12 	(matrix12 	),
 	.matrix13 	(matrix13 	),
 	.matrix21 	(matrix21 	),
 	.matrix22 	(matrix22 	),
 	.matrix23 	(matrix23 	),
 	.matrix31 	(matrix31 	),
 	.matrix32 	(matrix32 	),
 	.matrix33 	(matrix33 	)
);

reg 	vs_r 	;

always @(posedge clk)
	if(rst_n == 0)
		vs_r 	<= 1'b0;
	else 
		vs_r 	<= vs;

always @(posedge clk)
	if(~vs&&vs_r)
		$stop;
endmodule

2.3 边沿填充的卷积核仿真波形

  边沿复制后的数据为
在这里插入图片描述
  仿真波形为:
在这里插入图片描述
  可以看到3X3卷积模板生成无误。
  无边沿填充的卷积核只需要将martex

  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值