您的位置:首页 > 其它

FPGA图像处理系列:图像缩放

2016-03-24 21:25 246 查看
用了一晚上时间实现了一个Avalon-ST总线的简单图像缩放模块,将640*480的图像输入,变成320*240大小的图像输出。主要思想是,得到图像的行列计数值,根据要缩放的比例,在相应的行列值使能valid信号,比如我要将640*480图像缩小成320*240,那么只需控制将其隔行、隔列使能valid就行了。其实就是一个降采样。代码直接贴出

</pre><pre name="code" class="cpp">module ST_RESIZE(
// global clock & reset
input          	clk,
input	            reset_n,

// stream sink
input	[23:0]		sink_data,
input	      		sink_valid,
output         	sink_ready,
input          	sink_sop,
input          	sink_eop,

// stream source
output [23:0]     source_data,
output            source_valid,
input             source_ready,
output            source_sop,
output            source_eop

);

localparam CTRL_PKT_NUM     = 3;

assign sink_ready   =  source_ready;
assign source_sop   =  sink_sop;
assign source_eop   =  sink_eop;
//assign source_valid =  sink_valid;
//assign source_data  =  sink_data;

parameter WIDTH = 640;
parameter HEIGHT = 480;
parameter w_LOG_WIDTH = 320;
parameter w_LOG_HEIGHT = 240;
reg state;
localparam STATE_CTRL = 0;
localparam STATE_DATA = 1;
always@(posedge clk)begin
if(~reset_n)
state <= STATE_CTRL;
else if( process_en && sink_sop&& sink_data == 24'd15)
state <= STATE_CTRL;
else if( process_en && sink_sop&& sink_data == 24'd0)
state <= STATE_DATA;
end

reg [10:0]  h_count;
reg [10:0]  v_count;
wire process_en;
assign process_en = source_ready & sink_valid;
always@(posedge clk)begin
if(~reset_n)
h_count <= 11'b0;
else if( process_en && sink_sop && sink_data == 24'd0)
h_count <= 11'b0;
else if( process_en && h_count< WIDTH-1 && state == STATE_DATA)
h_count <= h_count + 1'b1;
else if( process_en &&  h_count== WIDTH-1 && state == STATE_DATA)
h_count <= 11'b0;
end

always@(posedge clk)begin
if(~reset_n)
v_count <= 11'b0;
else if( process_en && sink_sop&& sink_data == 24'd0)
v_count <= 11'b0;
else if( process_en && h_count == WIDTH-1 && state == STATE_DATA)
v_count <= v_count + 1'b1;
end

assign source_valid =(sink_valid & sink_sop & sink_data == 24'd15) |
(sink_valid & state == STATE_CTRL )|
(sink_valid & sink_sop & sink_data == 24'd00) |
( sink_valid & state == STATE_DATA & h_count[0]==0 & v_count[0]==0) |
( sink_valid & sink_eop )
;
//assign source_data =  sink_data;

always @(*) begin
case (state )
STATE_CTRL :
if(source_ready & sink_valid)begin
if(dot_cnt==0)source_data = { 4'b0,  w_LOG_WIDTH[ 7: 4], 4'b0,  w_LOG_WIDTH[11: 8], 4'b0,  w_LOG_WIDTH[15:12] };
if(dot_cnt==1)source_data = { 4'b0,  w_LOG_HEIGHT[11: 8], 4'b0, w_LOG_HEIGHT[15:12], 4'b0,  w_LOG_WIDTH[ 3: 0] };
if(dot_cnt==2)source_data = { 4'b0,            4'b0, 4'b0, w_LOG_HEIGHT[ 3: 0], 4'b0, w_LOG_HEIGHT[ 7: 4] };
end
STATE_DATA : source_data = sink_data;
default : source_data = sink_data;
endcase
end

reg [11:0] dot_cnt;
always @(posedge clk) begin
if (!reset_n) begin
dot_cnt <= 0;
end
else begin
if (dout_ready & source_ready)begin
if ((pkt_state == STATE_CTRL) )begin // control packet
if ( dot_cnt < (CTRL_PKT_NUM-1) )
dot_cnt <= dot_cnt + 11'd1;
else
dot_cnt <= 0;
end
end
end
endmodule


另外,假如对于一幅图像(1920*1080),我想把它缩小到任意的大小,比如320*240大小:

对于水平的320像素,因为1920/320=6,因此只需设置一个列循环计数值,范围0-5,在等于5的时候,输出像素valid为1;

对于竖直方向的240,因为1080除以240不是整数,而是9/2。也就是说,需要每隔4.5行,就应该输出一个valid。为了使其整数化,可以等同为每隔9行输出两个valid。因此可以设置一个行循环计数值,范围0-8,在等于3或者等于8的时候,输出valid为1。代码如下:

module ST_RESIZE(
// global clock & reset
input          	clk,
input	            reset_n,

// stream sink
input	[15:0]		sink_data,
input	      		sink_valid,
output         	sink_ready,
input          	sink_sop,
input          	sink_eop,

// stream source
output [15:0]     source_data,
output            source_valid,
input             source_ready,
output            source_sop,
output            source_eop

);

assign sink_ready   =  source_ready;
assign source_sop   =  sink_sop;
assign source_eop   =  sink_eop;

parameter WIDTH = 1920;
parameter HEIGHT = 1080;

reg state;
localparam STATE_CTRL = 0;
localparam STATE_DATA = 1;
always@(posedge clk)begin
if(~reset_n)
state <= STATE_CTRL;
else if( process_en && sink_sop&& sink_data == 16'd15)
state <= STATE_CTRL;
else if( process_en && sink_sop&& sink_data == 16'd0)
state <= STATE_DATA;
end

reg [10:0]  h_count;
reg [10:0]  v_count;
wire process_en;
assign process_en = source_ready & sink_valid;

reg [3:0] h_step_count;
reg [3:0] v_step_count;
always@(posedge clk)begin
if(~reset_n)begin
h_count <= 11'b0;
h_step_count <= 4'b0;
end
else if( process_en && sink_sop && sink_data == 16'd0)begin
h_count <= 11'b0;
h_step_count <= 4'b0;
end
else if( process_en && h_count< WIDTH-1 && state == STATE_DATA)begin
h_count <= h_count + 1'b1;
if(h_step_count >= 4'd5)
h_step_count <= 4'b0;
else
h_step_count <= h_step_count+1;
end
else if( process_en &&  h_count== WIDTH-1 && state == STATE_DATA)begin
h_count <= 11'b0;
h_step_count <= 4'b0;
end
end

always@(posedge clk)begin
if(~reset_n)begin
v_count <= 11'b0;
v_step_count <= 4'b0;
end
else if( process_en && sink_sop&& sink_data == 16'd0)begin
v_count <= 11'b0;
v_step_count <= 4'b0;
end
else if( process_en && h_count == WIDTH-1 && state == STATE_DATA)begin
v_count <= v_count + 1'b1;
if(v_step_count >= 4'd8)
v_step_count <= 4'b0;
else
v_step_count <= v_step_count+1;
end
end

assign source_valid =(sink_valid & sink_sop & sink_data == 16'd15) | //
(sink_valid & state == STATE_CTRL )|
(sink_valid & sink_sop & sink_data == 16'd00) |
( sink_valid & state == STATE_DATA & h_step_count==4'd5 &( v_step_count==4'd3 | v_step_count==4'd8)) |
( sink_valid & sink_eop )
;

assign source_data =  sink_data;
endmodule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  FPGA 图像处理