图像边缘检测

发布于:2022-11-02 ⋅ 阅读:(394) ⋅ 点赞:(0)

实验任务:

通过串口助手把 200 行 x200 列数据传入 FPGA,对应三行三列的九个数进行 sobel 算法,把结果通过 vga 来显示,用两种颜色来区分是否是边界点。

Sobel 算法:

1、把图像每三行三列的数据分别乘上算子中对应位置的值再相加。然后进行如 下运算,得到相应方向(x 和 y)的 Dx 和 Dy。

Dx=(a3-a1)+(b3-b1)*2+c3-c1;

Dy=(a1-c1)+(a2-c2)*2+a3-c3;

2、对上面求得的 Dx 和 Dy 做平方和的平方根,再取近似值 Dx 和 Dy 的绝对值的 和得到 Dxy:

 

3、如果 Dxy 的值大于一个阈值,表示该点为边界点,就让 VGA 显示一个白点, 否则显示黑点。

4、把计算的结果通过 vga 显示,显示器会把是边界点的以白色像素显示,不是 边界点的以黑色像素点显示,于是得到了一幅图像的轮廓。

 框图解析:

a、gen_clk 模块为二分频模块,产生的 25Mhz 的时钟传给后面的所有模块,这样 相当于整个系统都是共用了一个时钟。

b、uart_rx 模块负责接收上位机传递过来的 40000 个数据,拼接的同时传给 sobel_ctrl 进行数据的缓存和运算,注意 uart_rx 模块的时钟变了,如果是采用波 特率为 9600 的话,此模块里面的波特计数器需要减半。

c、sobel_ctrl 模块实现数据的缓存和 sobel 算法的运算,结果传给 vga 模块。

d、vga 模块里面调用了一个 ram 存储器,用来存储 198x198 个数据(除去两行两 列),vga 模块负责 ram 的读写,让 ram 里面写的数据位 sobel_ctrl 模块处理好的 数据,读出来的数据需要给 rgb 进行显示的。

顶层模块设计

顶层模块示意图:

 顶层模块代码实现:

module sobel_top(
    input         wire          clk,
    input         wire          rst_n,
    input         wire          rx,
    output        wire  [7:0]   rgb,
    output        wire          hsync,
    output        wire          vsync
    );
wire    [7:0]    po_data;
wire             po_flag;
wire    [7:0]    rgb1;
wire             po_flag1;
wire    [7:0]    doutb;
wire             rd_flag;

uart_rx uart_rx_inst(
    .clk(clk2),
    .rst_n(rst_n),
    .rx(rx),
    .po_data(po_data),
    .po_flag(po_flag)
    );

fifo_ctrl fifo_ctrl_inst(
    .clk(clk2),
    .rst_n(rst_n),
    .rx_data(po_data),
    .pi_flag(po_flag),
    .rgb(rgb1),
    .po_flag(po_flag1)
    );

ram_ctrl ram_ctrl_inst(
    .clk(clk2),
    .rst_n(rst_n),
    .wr_en(po_flag1),
    .pi_data(rgb1),
    .doutb(doutb),
    .rd_flag(rd_flag)
    );

vga vga_inst(
    .clk2(clk2),
    .rst_n(rst_n),
    .doutb(doutb),
    .rd_flag(rd_flag),
    .hsync(hsync),
    .vsync(vsync),
    .rgb(rgb)
    );

  clk_wiz_0 clk_wiz_0_inst
   (
    // Clock out ports
    .clk_out1(clk2),     // output clk_out1
   // Clock in ports
    .clk_in1(clk)); 

endmodule

接收模块设计

接收模块示意图:

 

接收模块波形图:

接收模块代码实现:

module uart_rx(
    input       wire        clk,
    input       wire        rst_n,

    input       wire        rx,
    output      reg  [7:0]  po_data,
    output      reg         po_flag
    );

reg        rx1;
reg        rx2;
reg        rx2_reg;
reg        rx_flag;
reg        bit_flag;
reg  [3:0] bit_cnt;
reg  [12:0] baud_cnt;

always @(posedge clk) begin
    rx1<=rx;
    rx2<=rx1;

    rx2_reg<=rx2;
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        baud_cnt<='d0;
    end
    else if(baud_cnt=='d2603) begin
        baud_cnt<='d0;
    end
    else if(bit_cnt=='d8 &&  bit_flag==1'b1) begin
        baud_cnt<='d0;
    end
    else if (rx_flag==1'b1) begin
        baud_cnt<=baud_cnt+1'b1;

    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        bit_flag<=1'b0;
    end
    else if (baud_cnt=='d1301) begin
        bit_flag<=1'b1;
    end
    else begin
        bit_flag<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        bit_cnt<='d0;

    end
    else if(bit_cnt=='d8) begin
        bit_cnt<='d0;
    end
    else if (bit_flag==1'b1) begin
        bit_cnt<=bit_cnt+1'b1;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        rx_flag<=1'b0;
    end
    else if (rx2_reg==1'b1 && rx2==1'b0) begin
        rx_flag<=1'b1;
    end

    else if(bit_cnt=='d8 &&  bit_flag==1'b1) begin
        rx_flag<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        po_data<='d0;
    end
    else if (bit_flag==1'b1 && bit_cnt>=1'b1) begin
        po_data<={rx2,po_data[7:1]};
    end
end
always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        po_flag<=1'b0;

    end
    else if (bit_cnt=='d8 &&  bit_flag==1'b1) begin
        po_flag<=1'b1;
    end
    else begin
        po_flag<=1'b0;
    end
end
endmodule

 sobel控制模块设计

 sobel控制模块示意图:

  sobel控制模块波形图:

 

  sobel控制模块代码实现:

module fifo_ctrl(
    input          wire           clk,
    input          wire           rst_n,
    input          wire  [7:0]    rx_data,
    input          wire           pi_flag,
    output         reg   [7:0]    rgb,
    output         reg            po_flag
    );
    reg     [6:0]    cnt_col;
    reg     [6:0]    cnt_row;
    reg              wr_en1;
    reg              wr_en2;
    reg              wr_en1_pre1;
    reg              wr_en1_pre2;
    reg     [7:0]    data_in1;
    reg     [7:0]    data_in2;
    reg              rd_en;
    reg              flag_shift;
    reg              flag_d;
    reg              flag_d_pre;
    wire             full1,empty1,full2,empty2;
    wire   [7:0]     dout1;
    reg    [7:0]     dout1_t;
    reg    [7:0]     dout1_tt;
    wire   [7:0]     dout2;
    reg    [7:0]     dout2_t;
    reg    [7:0]     dout2_tt;
    reg    [7:0]     rx_data_t;
    reg    [7:0]     rx_data_tt;
    reg    [7:0]     dx;
    reg    [7:0]     dy;
    reg              flag_abs;
    reg    [7:0]     abs_dx;
    reg    [7:0]     abs_dy;
    reg              flag_dxy;
    reg    [7:0]     dxy;
    reg              flag_rgb;
always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        cnt_col<='d0;
    end
    else if(cnt_col=='d199) begin
        cnt_col<='d0;
    end
    else if (pi_flag==1'b1) begin
        cnt_col<=cnt_col+1'b1;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        cnt_row<='d0;
    end
    else if (pi_flag==1'b1 && cnt_col=='d199 && cnt_row=='d199) begin
        cnt_row<='d0;
    end
    else if(pi_flag==1'b1 && cnt_col=='d199) begin
        cnt_row<=cnt_row+1'b1;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        wr_en1<=1'b0;
    end
    else if (cnt_row=='d0 && pi_flag==1'b1) begin
        wr_en1<=1'b1;
    end
    else if(wr_en1_pre1==1'b1) begin
        wr_en1<=1'b1;
    end
    else begin
        wr_en1<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        wr_en1_pre1<=1'b0;
    end
    else if (wr_en1_pre2==1'b1) begin
        wr_en1_pre1<=1'b1;
    end
    else begin
        wr_en1_pre1<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        wr_en1_pre2<=1'b0;
    end
    else if (cnt_row>='d2 && cnt_row<='d84 && pi_flag==1'b1) begin
        wr_en1_pre2<=1'b1;
    end
    else begin
        wr_en1_pre2<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        wr_en2<=1'b0;
    end
    else if (cnt_row>='d1 && cnt_row<='d84 && pi_flag==1'b1) begin
        wr_en2<=1'b1;
    end
    else begin
        wr_en2<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        data_in1<='d0;
    end
    else if (cnt_row=='d0 && pi_flag==1'b1) begin
        data_in1<=rx_data;
    end
    else if(wr_en1_pre1==1'b1) begin
        data_in1<=dout2;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        data_in2<='d0;
    end
    else if (cnt_row>='d1 && cnt_row<='d84 && wr_en2==1'b1) begin
        data_in2<=rx_data;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        rd_en<=1'b0;
    end
    else if (cnt_row>='d2 && cnt_row<='d85 && pi_flag==1'b1) begin
        rd_en<=1'b1;
    end
    else begin
        rd_en<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        flag_shift<=1'b0;
    end
    else if (rd_en==1'b1) begin
        flag_shift<=1'b1;
    end
    else begin
        flag_shift<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        flag_d_pre<=1'b0;
    end
    else if (cnt_row>='d2 && cnt_col>='d2) begin
        flag_d_pre<=pi_flag;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        flag_d<=1'b0;
    end
    else begin
        flag_d<=flag_d_pre;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        dout1_t<='d0;
        dout1_tt<='d0;
        dout2_t<='d0;
        dout2_tt<='d0;
        rx_data_t<='d0;
        rx_data_tt<='d0;
    end
    else if (flag_shift==1'b1) begin
        dout1_t<=dout1;
        dout1_tt<=dout1_t;
        dout2_t<=dout2;
        dout2_tt<=dout2_t;
        rx_data_t<=rx_data;
        rx_data_tt<=rx_data_t;        
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        flag_abs<=1'b0;
    end
    else begin
        flag_abs<=flag_d;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        flag_dxy<=1'b0;
    end
    else begin
        flag_dxy<=flag_abs;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        flag_rgb<=1'b0;
    end
    else begin
        flag_rgb<=flag_dxy;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        dx<='d0;
    end
    else if (flag_d==1'b1) begin
        dx<=dout1_tt-dout1+(dout2_tt-dout2)*2+rx_data_tt-rx_data;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        dy<='d0;
    end
    else if (flag_d==1'b1) begin
        dy<=dout1-rx_data+(dout1_t-rx_data_t)*2+dout1_tt-rx_data_tt;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        abs_dx<='d0;
    end
    else if (flag_abs==1'b1 && dx[7]==1'b1) begin
        abs_dx<=~dx+1'b1;
    end
    else if(flag_abs==1'b1 && dx[7]==1'b0) begin
        abs_dx<=dx;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        abs_dy<='d0;
    end
    else if (flag_abs==1'b1 && dy[7]==1'b1) begin
        abs_dy<=~dy+1'b1;
    end
    else if(flag_abs==1'b1 && dy[7]==1'b0) begin
        abs_dy<=dy;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        dxy<='d0;
    end
    else if (flag_dxy==1'b1) begin
        dxy<=abs_dx+abs_dy;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        rgb<='d0;
    end
    else if (flag_rgb==1'b1 && dxy>10) begin
        rgb<=8'hff;
    end
    else if(flag_rgb==1'b1 && dxy<=10) begin
        rgb<=8'h00;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        po_flag<=1'b0;
    end
    else if (flag_rgb==1'b1) begin
        po_flag<=1'b1;
    end
    else begin
        po_flag<=1'b0;
    end
end
fifo_generator_0 fifo_generator_0_inst1 (
  .clk(clk),      // input wire clk
  .din(data_in1),      // input wire [7 : 0] din
  .wr_en(wr_en1),  // input wire wr_en
  .rd_en(rd_en),  // input wire rd_en
  .dout(dout1),    // output wire [7 : 0] dout
  .full(full1),    // output wire full
  .empty(empty1)  // output wire empty
);
fifo_generator_0 fifo_generator_0_inst2 (
  .clk(clk),      // input wire clk
  .din(data_in2),      // input wire [7 : 0] din
  .wr_en(wr_en2),  // input wire wr_en
  .rd_en(rd_en),  // input wire rd_en
  .dout(dout2),    // output wire [7 : 0] dout
  .full(full2),    // output wire full
  .empty(empty2)  // output wire empty
);
endmodule 

ram模块设计

ram模块示意图:

 ram模块波形图:

  ram模块代码实现:

module ram_ctrl(
    input     wire         clk,
    input     wire         rst_n,
    input     wire         wr_en,
    input     wire [7:0]   pi_data,
    output    wire [7:0]   doutb,
    output    reg          rd_flag
    );


reg  [15:0]     wr_addr;
reg  [15:0]     rd_addr;
reg             rd_en;


always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        rd_flag<=1'b0;        
    end
    else if (wr_addr=='d39999) begin
        rd_flag<=1'b1;
    end
    else begin
        rd_flag<=1'b0;
    end
end

always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        rd_en<=1'b0;        
    end
    else if (rd_addr=='d39999) begin
        rd_en<=1'b0;    
    end
    else if(rd_flag==1'b1) begin
        rd_en<=1'b1;
    end
end


always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        wr_addr<='d0;        
    end
    else if(wr_en==1'b1 && wr_addr=='d39999) begin
        wr_addr<='d0;
    end
    else if (wr_en==1'b1) begin
        wr_addr<=wr_addr+1'b1;
    end
end
always @(posedge clk or posedge rst_n) begin
    if (!rst_n) begin
        rd_addr<='d0;        
    end
    else if(rd_addr=='d39999 && rd_en==1'b1) begin
        rd_addr<='d0;    
    end
    else if (rd_en==1'b1) begin
        rd_addr<=rd_addr+1'b1;
    end
end
ram_8x40000 ram_8x40000_inst (
  .clka(clk),    // input wire clka
  .wea(wr_en),      // input wire [0 : 0] wea
  .addra(wr_addr),  // input wire [15 : 0] addra
  .dina(pi_data),    // input wire [7 : 0] dina
  .clkb(clk),    // input wire clkb
  .enb(rd_en),      // input wire enb
  .addrb(rd_addr),  // input wire [15 : 0] addrb
  .doutb(doutb)  // output wire [7 : 0] doutb
);
endmodule

vga模块设计

vga模块示意图:

 

vga模块波形图:

 

  vga模块代码实现:

module vga(
    input         wire           clk2,
    input         wire           rst_n,
    input         wire [7:0]     doutb,
    input         wire           rd_flag,
    output        reg            hsync,
    output        reg            vsync,
    output        reg  [7:0]     rgb
    );

    reg         [9:0]          cnt_h;
    reg         [9:0]          cnt_v;
    reg                        cnt_flag;
    reg                           rd_flag_r;

always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        rd_flag_r<=1'b0;
    end
    else begin
        rd_flag_r<=rd_flag;
    end
end

always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        cnt_flag<=1'b0;
    end
    else if(rd_flag_r==1'b1) begin
        cnt_flag<=1'b1;
    end
end

always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        cnt_h<='d0;
    end
    else if (cnt_h=='d799) begin
        cnt_h<='d0;
    end
    else if(cnt_flag==1'b1) begin
        cnt_h<=cnt_h+1'b1;
    end
end

always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        cnt_v<='d0;    
    end
    else if (cnt_v=='d524 && cnt_h=='d799) begin
        cnt_v<='d0;    
    end
    else if(cnt_h=='d799) begin
        cnt_v<=cnt_v+1'b1;
    end
end
always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        hsync<=1'b1;
    end
    else if (cnt_h=='d95) begin
        hsync<=1'b0;
    end
    else if(cnt_h=='d799) begin
        hsync<=1'b1;
    end
end
always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        vsync<=1'b1;
    end
    else if (cnt_v=='d1 && cnt_h=='d799) begin
        vsync<=1'b0;
    end
    else if(cnt_v=='d524 && cnt_h=='d799) begin
        vsync<=1'b1;
    end
end

always @(posedge clk2 or posedge rst_n) begin
    if (!rst_n) begin
        rgb<='d0;
    end
    else  begin
        rgb<=doutb;
    end    
end
endmodule

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到