FPGA图像处理之获取窗口

最近在学习使用FPGA做一些图像去噪算法,实现算法的前提与基础是获取NN窗口。而一般图像传感器都是一行一行地输出像素数据,所以要获取NN窗口,至少得缓存N-1行数据。下面以3*3窗口为例讲解如何获取窗口。
在这里插入图片描述
如上图,可以用两个fifo实现两行缓存,数据缓存分为以下几步:

  1. 每当图像传感器输出数据有效时,开始写入fifo0(line_buffer(0));
  2. 当fifo0写满一行之后,且图像传感器输出数据有效,则开始读取fifo0的数据(line_out(0)),并将读出的数据写入fifo1(line_buffer(1));
  3. 当fifo1写满一行之后,且图像传感器输出数据有效,则开始读取fifo1的数据(line_out(1));
  4. 按照上述过程,当两个fifo都分别写满一行,那么din,line_out(0),line_out(1)就是连续的3行数据,并且列对齐;
  5. 分别利用移位寄存器对din,line_out(0),line_out(1)打两拍,则得到3*3的数据。

缓存代码如下:

wire fifo3_wr_en, fifo3_rd_en;
wire[9:0] fifo3_data_count;
wire fifo3_empty, fifo3_full;
wire[15:0] fifo3_dout;
parameter line_num = 10’d640; //一行的像素数

assign fifo3_wr_en = image_sensor_href; //数据有效则写第一行fifo
assign fifo3_rd_en = (fifo3_wr_en&&(fifo3_data_count>=line_num)) ? 1 : 0; //第一行fifo缓存完整的一行之后则开始读出

fifo_generator_3 sdff_fifo3(
.clk(image_sensor_pclk), // input wire clk
.srst(image_sensor_vsync_r), // input wire srst
.din(gray), // input wire [15 : 0] din
.wr_en(fifo3_wr_en), // input wire wr_en
.rd_en(fifo3_rd_en), // input wire rd_en
.dout(fifo3_dout), // output wire [15 : 0] dout
.full(fifo3_full), // output wire full
.empty(fifo3_empty), // output wire empty
.data_count(fifo3_data_count) // output wire [9 : 0] data_count
);

wire fifo4_wr_en, fifo4_rd_en;
wire[9:0] fifo4_data_count;
wire fifo4_empty, fifo4_full;
wire[15:0] fifo4_dout;

assign fifo4_wr_en = fifo3_rd_en; //读第一行fifo的同时写第二行fifo
assign fifo4_rd_en = (fifo3_wr_en&&(fifo4_data_count>=line_num)) ? 1 : 0; //第二行fifo缓存完整的一行之后则开始读出

fifo_generator_4 sdff_fifo4(
.clk(image_sensor_pclk), // input wire clk
.srst(image_sensor_vsync_r), // input wire srst
.din(fifo3_dout), // input wire [15 : 0] din
.wr_en(fifo4_wr_en), // input wire wr_en
.rd_en(fifo4_rd_en), // input wire rd_en
.dout(fifo4_dout), // output wire [15 : 0] dout
.full(fifo4_full), // output wire full
.empty(fifo4_empty), // output wire empty
.data_count(fifo4_data_count) // output wire [9 : 0] data_count
);

使用移位寄存器对信号打拍的代码如下:
//
reg[15:0] tmp0_0;
reg[15:0] tmp0_1;

always @(posedge clk)
begin
tmp0_0 <= line0_in; //第一行数据
tmp0_1 <= tmp0_0;
end

//
reg[15:0] tmp1_0;
reg[15:0] tmp1_1;

always @(posedge clk)
begin
tmp1_0 <= line1_in; //第二行数据
tmp1_1 <= tmp1_0;
end
/
reg[15:0] tmp2_0;
reg[15:0] tmp2_1;

always @(posedge clk)
begin
tmp2_0 <= line2_in; //第三行数据
tmp2_1 <= tmp2_0;
end

posted @ 2020-07-30 20:18  萌萌哒程序猴  阅读(90)  评论(0编辑  收藏  举报