FPGA实现腐蚀膨胀(形态学滤波)

一、二值图像

对于腐蚀膨胀,输入必须是二值图像。 二值图像就是指图像上的每一个像素只有两种可能的取值或灰度等级状态,即只有0和1(黑和白),当然也可以设置成0和255,反正只有两种状态就行。

二、形态学滤波 

形态学滤波有四种,分别是腐蚀、膨胀、开运算、闭运算。 

1、腐蚀:是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的物体。 

腐蚀就是用该3*3窗口遍历二值图像上的每个像素,将窗口内的9个像素进行与运算 。P=P11&P12&P13&P21&P22&P23&P31&P32&P33(1代表白色,0代表黑色)

54715b706cce4504a6b6f933023e9704.png

2、膨胀:是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。可以用来填补物体中的空洞。

膨胀就是进行或运算。P=P11∣P12∣P13∣P21∣P22∣P23∣P31∣P32∣P33 

93271f3d1bee4b0a8cebab66d6222ec5.png

3、开运算: 先腐蚀后膨胀。

4、闭运算:先膨胀后腐蚀。 

三、腐蚀(先二值化再腐蚀)

1、代码

以下是二值化代码 

module binary
(
input   wire                clk                     ,   //时钟
input   wire                rst_n                   ,   //复位

input   wire                gray_hs_out             ,   //行同步
input   wire                gray_vs_out             ,   //场同步
input   wire    [ 7:0]      gray                    ,   //数据
input   wire                oValid                  ,   //数据使能

input   wire    [ 7:0]      value                   ,   //阈值

output  wire                bina_hsync              ,   //二值行同步
output  wire                bina_vsync              ,   //二值场同步
output  wire    [ 7:0]      bina_data               ,   //二值数据
output  wire                bina_de                     //二值数据使能
);
//==========================================================================
//==                        代码
//==========================================================================
assign bina_hsync = gray_hs_out;
assign bina_vsync = gray_vs_out;
assign bina_de    = oValid;
assign bina_data  = (gray > 127) ? 8'hff : 8'h00;



endmodule

以下是腐蚀代码: 

module erode
(
input   wire                clk                     ,   //时钟
input   wire                rst_n                   ,   //复位
//input ---------------------------------------------
input   wire                bina_hsync              ,   //bina分量行同步
input   wire                bina_vsync              ,   //bina分量场同步
input   wire    [ 7:0]      bina_data               ,   //bina分量数据
input   wire                bina_de                 ,   //bina分量数据使能
//output --------------------------------------------
output  wire                erode_hsync             ,   //erode行同步
output  wire                erode_vsync             ,   //erode场同步
output  wire    [ 7:0]      erode_data              ,   //erode数据
output  wire                erode_de                    //erode数据使能
);

wire [7:0]     filter_11,filter_12,filter_13;
wire [7:0]     filter_21,filter_22,filter_23;
wire [7:0]     filter_31,filter_32,filter_33;

reg     [ 2:0]              bina_de_r               ;   //使能打拍
reg     [ 2:0]              bina_hsync_r            ;   //行同步打拍
reg     [ 2:0]              bina_vsync_r            ;   //场同步打拍

reg                         erode_1                 ;
reg                         erode_2                 ;
reg                         erode_3                 ;
reg                         erode                   ;


//==========================================================================
//==    模块例化,耗费1clk
//==========================================================================
filter_3x3 filter_3x3_inst(
    .clk      (clk      ),
    .rst_n    (rst_n    ),
	.gray_de  (bina_de  ),	 
    .iData    (bina_data),

    .oData_11 (filter_11), .oData_12 (filter_12), .oData_13 (filter_13),
    .oData_21 (filter_21), .oData_22 (filter_22), .oData_23 (filter_23),
    .oData_31 (filter_31), .oData_32 (filter_32), .oData_33 (filter_33)
);


//==============================================================================
//==    腐蚀,耗费2clk
//==============================================================================
//clk1,三行各自相与
//---------------------------------------------------
always @ (posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        erode_1 <= 'd0;
        erode_2 <= 'd0;
        erode_3 <= 'd0;
    end
    else begin
        erode_1 <= filter_11 && filter_12 && filter_13;
        erode_2 <= filter_21 && filter_22 && filter_23;
        erode_3 <= filter_31 && filter_32 && filter_33;
    end
end

//clk2,全部相与
//---------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        erode <= 'd0;
    end
    else begin
        erode <= erode_1 && erode_2 && erode_3;
    end
end

//==========================================================================
//==    信号值输出
//==========================================================================
assign erode_data = erode ? 8'hff : 8'h00;

//==========================================================================
//==    信号同步(打三拍)
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        bina_de_r    <= 3'b0;
        bina_hsync_r <= 3'b0;
        bina_vsync_r <= 3'b0;
    end
    else begin  
        bina_de_r    <= {bina_de_r[1:0],    bina_de};
        bina_hsync_r <= {bina_hsync_r[1:0], bina_hsync};
        bina_vsync_r <= {bina_vsync_r[1:0], bina_vsync};
    end
end

assign erode_de    = bina_de_r[2];
assign erode_hsync = bina_hsync_r[2];
assign erode_vsync = bina_vsync_r[2];


endmodule

 2、效果图

原图:

ec85f02a092d4daab5066840ea7af05d.bmp

FPGA二值化图: 

1809e720ca2d449fa98d5c92a9e5d392.bmp  

FPGA二值化后的腐蚀图:

ab55d2c6f06e4c6289e07072b001c9e0.bmp

 FPGA腐蚀图(上板)

 

 

MATLAB二值化后的腐蚀图 

b8d118d4479a406fb8ede78c8ed9a858.bmp

FPGA与MATLAB的效果一致,都把一些白色的明亮区域给腐蚀掉啦,实验成功。 

四、膨胀 

 1、代码

二值化代码同上,稍微改下端口名就可

以下是膨胀代码: 

module dilate
(
input   wire                clk                     ,   //时钟
input   wire                rst_n                   ,   //复位
//input ---------------------------------------------
input   wire                bina_hsync              ,   //bina分量行同步
input   wire                bina_vsync              ,   //bina分量场同步
input   wire    [ 7:0]      bina_data               ,   //bina分量数据
input   wire                bina_de                 ,   //bina分量数据使能
//output --------------------------------------------
output  wire                dilate_hsync             ,   //dilate行同步
output  wire                dilate_vsync             ,   //dilate场同步
output  wire    [ 7:0]      dilate_data              ,   //dilate数据
output  wire                dilate_de                    //dilate数据使能
);

wire [7:0]     filter_11,filter_12,filter_13;
wire [7:0]     filter_21,filter_22,filter_23;
wire [7:0]     filter_31,filter_32,filter_33;

reg     [ 2:0]              bina_de_r               ;   //使能打拍
reg     [ 2:0]              bina_hsync_r            ;   //行同步打拍
reg     [ 2:0]              bina_vsync_r            ;   //场同步打拍

reg                         dilate_1                 ;
reg                         dilate_2                 ;
reg                         dilate_3                 ;
reg                         dilate                   ;


//==========================================================================
//==    模块例化,耗费1clk
//==========================================================================
filter_3x3 filter_3x3_inst(
    .clk      (clk      ),
    .rst_n    (rst_n    ),
	.gray_de  (bina_de  ),	 
    .iData    (bina_data),

    .oData_11 (filter_11), .oData_12 (filter_12), .oData_13 (filter_13),
    .oData_21 (filter_21), .oData_22 (filter_22), .oData_23 (filter_23),
    .oData_31 (filter_31), .oData_32 (filter_32), .oData_33 (filter_33)
);


//==============================================================================
//==    腐蚀,耗费2clk
//==============================================================================
//clk1,三行各自相与
//---------------------------------------------------
always @ (posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        dilate_1 <= 'd0;
        dilate_2 <= 'd0;
        dilate_3 <= 'd0;
    end
    else begin
        dilate_1 <= filter_11 || filter_12 || filter_13;
        dilate_2 <= filter_21 || filter_22 || filter_23;
        dilate_3 <= filter_31 || filter_32 || filter_33;
    end
end

//clk2,全部相与
//---------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        dilate <= 'd0;
    end
    else begin
        dilate <= dilate_1 || dilate_2 || dilate_3;
    end
end

//==========================================================================
//==    信号值输出
//==========================================================================
assign dilate_data = dilate ? 8'hff : 8'h00;

//==========================================================================
//==    信号同步(打三拍)
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        bina_de_r    <= 3'b0;
        bina_hsync_r <= 3'b0;
        bina_vsync_r <= 3'b0;
    end
    else begin  
        bina_de_r    <= {bina_de_r[1:0],    bina_de};
        bina_hsync_r <= {bina_hsync_r[1:0], bina_hsync};
        bina_vsync_r <= {bina_vsync_r[1:0], bina_vsync};
    end
end

assign dilate_de    = bina_de_r[2];
assign dilate_hsync = bina_hsync_r[2];
assign dilate_vsync = bina_vsync_r[2];


endmodule

2、效果图 

原图: 

abce57deb52e496798b61dc7d83965a8.bmp

二值化图: 

b8e83c21bf0e4fe7ab419294c86dd91b.bmp

 膨胀图:

eae6a8bc46584d389acfa6b17a151f35.bmp

 MATLAB膨胀图:

384f320168d94e70b4c187534c6eb64d.bmp

FPGA与MATLAB的效果一致,都把一些白色的明亮区域给膨胀啦,实验成功。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值