芯路恒电子技术论坛

 找回密码
 立即注册

扫一扫,访问微社区

热搜: 活动
查看: 360|回复: 1

基于FPGA灰度图像的膨胀算法的实现

[复制链接]
  • TA的每日心情
    难过
    2018-4-24 14:02
  • 5

    主题

    5

    帖子

    10

    积分

    新手入门

    Rank: 1

    积分
    10
    发表于 2018-5-21 18:18:34 | 显示全部楼层 |阅读模式
    基于FPGA灰度图像的膨胀算法的实现
    1 背景知识
        腐蚀与膨胀是形态学滤波的两个基本运算,通过腐蚀和膨胀两种运算可以实现多种功能,主要如下:
    (1)消除噪声;
    (2)分割出独立的图像元素;
    (3)在图像中连接相邻的元素;
    (4)寻找图像中明显的极大值和极小值区域;
    (5)求出图像的梯度。
    image002.jpg
                                  
    图1 腐蚀膨胀示意图
    图1 a为大小为448X425像素的灰度级X射线图像;b使用半径为2个像素的圆盘形结构元对图像的腐蚀结果;c用相同的结构元对图像的膨胀结果。原图有Lixi公司提供。
    1)形态学滤波之膨胀
       膨胀(dialate)就是求局部最大值的操作。
       从数学角度来看就是将图像f和核(结构元)b进行卷积的一个过程。
       b的原点位于(x,y)处时,用一个平坦的结构元b在(x,y)处对图像f的膨胀,定义为图像f中与b重合区域的最大值,即:
    79c4f338527ab88be7f2c477c50d4ec.png       
       为了方便起见,将膨胀操作记为:
    bb5df7f441e946fe1344cfb01169b47.png
    (x,y)表示当前输入图像的行列坐标;
    f(x,y)表示坐标点(x,y)处的图像像素值;
    g(x,y)表示坐标点(x,y)处的滤波结果;
    (s,t)表示作用域。
    2 matlab仿真灰度图像的膨胀
    Matlab膨胀源码:
    %%imagedilate
    clc
    clearall
    img_a= imread('flower.bmp');
    figure,imshow(img_a);
    title('img_a rgb');
    img_b= rgb2gray(img_a);
    figure,imshow(img_b);
    title('img_b gary');
    a= [1,1,1;
         1,1,1;
         1,1,1]; %structural element
    b= [1,1,1,1,1;
         1,1,1,1,1;
         1,1,1,1,1;
         1,1,1,1,1;
         1,1,1,1,1];
    c = [1,1,1,1,1,1,1;
          1,1,1,1,1,1,1;
          1,1,1,1,1,1,1;
          1,1,1,1,1,1,1;
          1,1,1,1,1,1,1;
          1,1,1,1,1,1,1;
          1,1,1,1,1,1,1];
    img_c= imdilate(img_b,a);
    figure,imshow(img_c);
    title('img_c 3x3');
    img_d= imdilate(img_b,b);
    figure,imshow(img_d);
    title('img_d 5x5');
    img_e= imdilate(img_b,c);
    figure,imshow(img_e);
    title('img_e 7x7');



    image008.jpg image010.jpg image012.jpg image014.jpg image016.jpg


    3.1 膨胀模块的设计
    1)比较子模块
    2)一维形态学膨胀子模块
    3)二维形态学膨胀子模块
    1比较子模块
    为了代码更好的移植,我们将比较子模块设计为独立的子模块。
    Erode:输出俩个数据的较小值。
    image018.jpg

    比较子模块源码:
    /*
    Module name:  minmax.v
    Description:  
                  
    Data:         2018/03/14
    Engineer:     lipu
    e-mail:       137194782@qq.com
    */
    `timescale1ns/1ps
    moduleminmax(
          clk, //pixel clock
             rst_n,
             data_valid,
             din,
             din_r,
             dout_min,
             dout_max
             );
    parameterWIDTH = 8;        // data width 8 bit
    parameterUSE_REG = 1; // USE_REG = 1Data delay 1ns output.  USE_REG = 0 Don'tdelay.   
    input               clk;  //pixel clock
    input               rst_n;
    input               data_valid;
    input  [WIDTH-1:0] din;
    input  [WIDTH-1:0] din_r;
    output[WIDTH-1:0] dout_min;
    output[WIDTH-1:0] dout_max;     
    wireminmax_flag;
    wire[WIDTH-1:0] min_temp;
    wire[WIDTH-1:0] max_temp;
    reg  [WIDTH-1:0] min_reg;
    reg  [WIDTH-1:0] max_reg;
    // min or max flag
    assignminmax_flag = (din > din_r) ? 1'b1:1'b0;
    // min
    assignmin_temp = (minmax_flag == 1'b1) ? din_r : din;
    // max
    assignmax_temp = (minmax_flag == 1'b1) ? din : din_r;
    // USE_REG == 1
    generate
    if(USE_REG== 1)
    begin: MAP0
      always @(posedge clk) begin
        if(data_valid) begin
            min_reg <= #1 min_temp;
            max_reg <= #1 max_temp;
           end
      end
      assign dout_min = min_reg;
      assign dout_max = max_reg;
    end
    endgenerate
    //USE_REG == 0
    generate
    if(~(USE_REG== 1))
    begin: MAP1
      assign dout_min = min_temp;
      assign dout_max = max_temp;
    end
    endgenerate
    endmodule
    比较子模块仿真源码:
    /*
    Module name:  minmax_tb.v
    Description:            
    */
    `timescale1ns/1ps
    `defineWIDTH 8
    `defineCLK_PERIOD 10
    moduleminmax_tb();
           reg               clk; //pixel clock
             reg               rst_n;
             reg               data_valid;
             reg  [`WIDTH-1:0] din;
             reg  [`WIDTH-1:0] din_r;
             wire [`WIDTH-1:0] dout_min;
             wire [`WIDTH-1:0] dout_max;
    minmaxminmax_inst(
            .clk(clk),  //pixel clock
              .rst_n(rst_n),
              .data_valid(data_valid),
              .din(din),
                  .din_r(din_r),
              .dout_min(dout_min),
              .dout_max(dout_max)
             );
             initial begin
               clk = 0;
                   rst_n = 0;
                   data_valid = 0;
                   #(`CLK_PERIOD*10);
                   rst_n = 1;
               #(`CLK_PERIOD*10);
                   data_valid = 1;
                   #(`CLK_PERIOD*100);
                   data_valid = 0;
                   #(`CLK_PERIOD*10);
                   $stop;
             end
    always#(`CLK_PERIOD/2)       clk = ~clk;  
    always@(posedge clk or negedge rst_n) begin
      if(!rst_n)
        din <= 8'd0;
      else if(data_valid)
        din <= {$random}%255;
      else
        din <= 8'b0;
    end
    always@(posedge clk or negedge rst_n) begin
      if(!rst_n)
        din_r <= 8'd0;
      else if(data_valid)
        din_r <= din;
      else
        din_r <= 8'b0;
    end
    Endmodule
    比较子模块仿真波形
      
      
      t
      
      t+1
      
      t+2
      
      t+3
      
      t+4
      
      t+5
      
      t+6
      
      t+7
      
      t+8
      
      t+9
      
      t+10
      
      din
      
      128
      
      42
      
      232
      
      92
      
      72
      
      77
      
      95
      
      37
      
      216
      
      184
      
      198
      
      din_r
      
      X
      
      128
      
      42
      
      232
      
      92
      
      72
      
      77
      
      95
      
      37
      
      216
      
      184
      
      dout_min
      
      X
      
      X
      
      42
      
      42
      
      92
      
      72
      
      72
      
      77
      
      37
      
      37
      
      184
      
      dout_max
      
      X
      
      X
      
      128
      
      232
      
      232
      
      92
      
      77
      
      95
      
      95
      
      216
      
      216
      
    image020.jpg

    当我们需要做膨胀算法时,数据取dout_max;当我们需要做腐蚀算法时,数据取dout_min。

    (2)一维形态学膨胀模块设计
    我们要完成对nxn窗口的腐蚀或者膨胀首先我们要做图像行的一维腐蚀或膨胀。例如我们要做3x3窗口的腐蚀或膨胀,一维形态学腐蚀或膨胀如图所示:
    image022.jpg

    (3) 二维形态学腐蚀与膨胀子模块设计
    image024.jpg

    形态学膨胀结果演示:
    顶层源码:
    ////////////////////////////////////////////////////////////////
    wire[15:0] rgb;
    wirehs;
    wirevs;
    wirede;  

    wireo_hs;
    wireo_vs;
    wireo_de;                                 
    wire[7 : 0]            o_y_8b;
    wire[7 : 0]            o_cb_8b;
    wire[7 : 0]            o_cr_8b;
    wire[7 : 0]      dout;

    //assign TFT_rgb ={o_y_8b[7:3],o_y_8b[7:2],o_y_8b[7:3]};    //Y
    //assign TFT_rgb ={o_cb_8b[7:3],o_cb_8b[7:2],o_cb_8b[7:3]}; //cb
    //assign TFT_rgb ={o_cr_8b[7:3],o_cr_8b[7:2],o_cr_8b[7:3]}; //cr

    tft_ctrltft_ctrl(
           .Clk9M(clk9M),    //系统输入时钟9MHZ
           .Rst_n(Rst_n),     //复位输入,低电平复位
           .data_in({Rd_data[7:0],Rd_data[15:8]}),  //待显示数据
           .hcount(),             //TFT行扫描计数器
           .vcount(),             //TFT场扫描计数器
           .TFT_RGB(rgb),  //TFT数据输出
           .TFT_HS(hs),             //TFT行同步信号
           .TFT_VS(vs),              //TFT场同步信号
           .TFT_CLK(TFT_clk),         //TFT像素时钟
           .TFT_DE(de),             //TFT数据使能
           .TFT_begin(tft_begin),
           .TFT_PWM(TFT_pwm)            //TFT背光控制
           );
    rgb_to_ycbcr  rgb_to_ycbcr_inst(
                                  .clk(TFT_clk),
                                  .i_r_8b({rgb[15:11],3'b0}),
                                  .i_g_8b({rgb[10:5],2'b0}),
                                  .i_b_8b({rgb[4:0],3'b0}),

                                  .i_h_sync(hs),
                                  .i_v_sync(vs),
                                  .i_data_en(de),

                                  .o_y_8b(o_y_8b),
                                  .o_cb_8b(o_cb_8b),
                                  .o_cr_8b(o_cr_8b),

                                  .o_h_sync(o_hs),
                                  .o_v_sync(o_vs),                                                                                                
                                  .o_data_en(o_de)                                                                                                
                                              );
    /*                                       
    erode erode_inst(
         .clk(TFT_clk),
                  .rst_n(Rst_n),
                  .hs_in(o_hs),
                  .vs_in(o_vs),
                  .din(o_y_8b),
                  .din_valid(o_de),
                  .dout(dout),
                  .dout_valid(TFT_de),
                  .hs_out(TFT_hs),
                  .vs_out(TFT_vs)
                  );     
    */
    dilatedilate_inst(
          .clk(TFT_clk),
                  .rst_n(Rst_n),
                  .hs_in(o_hs),
                  .vs_in(o_vs),
                  .din(o_y_8b),
                  .din_valid(o_de),
                  .dout(dout),
                  .dout_valid(TFT_de),
                  .hs_out(TFT_hs),
                  .vs_out(TFT_vs)
                  );            
    assignTFT_rgb = {dout[7:3],dout[7:2],dout[7:3]};    //Y
    //assign TFT_rgb ={o_y_8b[7:3],o_y_8b[7:2],o_y_8b[7:3]};    //Y   
    image026.jpg image028.jpg



    欢迎大家关注我的微信公众号:FPGA开源工作室:
    image029.jpg image030.jpg


    image004.gif
    image006.gif
    回复

    使用道具 举报

  • TA的每日心情
    开心
    5 小时前
  • 12

    主题

    141

    帖子

    2502

    积分

    超级版主

    Rank: 8Rank: 8

    积分
    2502
    发表于 2018-5-21 19:19:49 | 显示全部楼层
    楼主图片编排貌似乱了
    回复 支持 反对

    使用道具 举报

    *滑动验证:
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|小黑屋|手机版|Archiver|芯路恒电子技术论坛  

    GMT+8, 2018-6-19 12:49 , Processed in 0.232574 second(s), 10 queries , File On.

    Powered by Discuz! X3.3

    © 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

    快速回复 返回顶部 返回列表