• FPGA实现图像二值形态学滤波——腐蚀膨胀


    一、二值图像

    二值图像(Binary Image)是指图像上的每一个像素只有两种可能的取值或灰度等级状态。简言之,在图像中灰度等级只有两种0或255(黑或白).

    二、形态学

    形态学,即数学形态学(Mathematical Morphology),是图像处理中应用最为广泛的技术之一,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,如边界和连通区域等,便于后续图像识别等工作。

    常用场景:边缘检测,孔洞填充,纹理分析、形态骨架提取、形状识别、图像分割、角点提取,图像恢复与重建、图像压缩等。

    基本的算法膨胀腐蚀,开操作,闭操作;

    先腐蚀后膨胀的过程称为开运算。它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。
    先膨胀后腐蚀的过程称为闭运算。它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。

    实现方式:在图像中移动一个结构元素(滤波窗口),后将结构元素与下面的二值图像进行交并等集合运算。因此这种二值形态算法可转换成集合的逻辑运算,简单且适用于并行处理,本文则采用硬件FPGA实现。

    三、腐蚀膨胀

    对于腐蚀膨胀,输入图像必须是二值图像,通过腐蚀膨胀运算可实现多种功能,如:
    (1)抑制噪声
    (2)分割出独立元素
    (3)连接相邻的元素
    (4)寻找图像中明显的极大值和极小值区域
    (5)求图像梯度

    腐蚀膨胀的原理

    1、腐蚀

    腐蚀(Erode)是求局部最小值的操作,可消除边界点,使边界向内部收缩,从而消除小且无意义的物体。
    以 3x3 模板为例,1 代表白色,0代表黑色。
    腐蚀就是用该3*3窗口遍历二值图像上的每个像素,将窗口内的9个像素进行相与运算,结果为 1 则输出为 1,否则为0。
    在这里插入图片描述

    2、膨胀

    膨胀(Dialate)是求局部最大值的操作,能将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程,从而填补物体中空洞。
    膨胀即这 9 个像素相或。
    在这里插入图片描述
    注意:如果背景与图像的颜色互换(0表示白,1表示黑),那么只需要将图像膨胀与腐蚀的与或运算相互颠倒即可。

    四、matlba实现腐蚀膨胀

    clc;
    clear all;
    close all;
    
    RGB = imread('二值化图像.bmp');                %读图
    [ROW,COL, DIM] = size(RGB);              %得到图像行列数
    %------------------------------< Erode >-----------------------------------
    Erode_img = zeros(ROW,COL);
    for r = 2:ROW-1
        for c = 2:COL-1
            and1 = bitand(RGB(r-1, c-1), bitand(RGB(r-1, c), RGB(r-1, c+1)));
            and2 = bitand(RGB(  r, c-1), bitand(RGB(  r, c), RGB(  r, c+1)));
            and3 = bitand(RGB(r+1, c-1), bitand(RGB(r+1, c), RGB(r+1, c+1)));
            Erode_img(r, c) = bitand(and1, bitand(and2, and3));
        end
    end
    %------------------------------< Dilate >----------------------------------
    Dilate_img = zeros(ROW,COL);
    for r = 2:ROW-1
        for c = 2:COL-1
            or1 = bitor(RGB(r-1, c-1), bitor(RGB(r-1, c), RGB(r-1, c+1)));
            or2 = bitor(RGB(  r, c-1), bitor(RGB(  r, c), RGB(  r, c+1)));
            or3 = bitor(RGB(r+1, c-1), bitor(RGB(r+1, c), RGB(r+1, c+1)));
            Dilate_img(r, c) = bitor(or1, bitor(or2, or3));
        end
    end
    %------------------------------< show >------------------------------------
    figure;         imshow(RGB);       title('原图');
    subplot(2,2,1); imshow(Erode_img); title('腐蚀');
    imwrite (Erode_img,'Erode_img.bmp');
    subplot(2,2,2); imshow(Dilate_img);title('膨胀');
    imwrite (Dilate_img,'Dilate_img.bmp');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    五、FPGA实现腐蚀

    二值化模块、3*3窗口生成模块、腐蚀模块
    在这里插入图片描述

    verilog实现二值化

    module two(
        input            clk,
        input            rst_n,
    	 
        input   wire		iValid,
    
    	 input [7:0]  iData,
    	 output  reg out_Valid,
        output reg  [7:0]oData_two   
    );
    
     parameter THRESHOLD = 8'd150; //二值化的阈值
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n)
    	     oData_two <= 0;
    	 else if (iData > THRESHOLD)
    	     oData_two <= 8'd255;
    	 else
    	     oData_two <= 0;
    		  
    always @ (posedge clk or negedge rst_n)
        if(!rst_n)
    	     out_Valid <= 0;
    	 else 
    	     out_Valid <= iValid;
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    verlog实现腐蚀

    module Erode(
        input            clk,
        input            rst_n,
    	 
        input   wire		iValid					,
    
        input   [7:0]     filter_11,filter_12,filter_13, //生成的3*3窗口数据
        input   [7:0]     filter_21,filter_22,filter_23,
        input   [7:0]     filter_31,filter_32,filter_33,
    
        output  			 Erode_de    ,//de同步信号
    	 
        output  wire  [7:0]    Erode_data  
    
    );
    
    reg [1:0]           de_shift1 ;  
    
    
    reg  g1,g2,g3,g;
    
    
    //---------------------------------------------------
    //                   腐蚀算法的流水并行运算
    //---------------------------------------------------
    
    //clk1,进行所有行的与运算 , &&逻辑与
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
    	     g1 <= 1'b0;
    		  g2 <= 1'b0;
    		  g3 <= 1'b0;
    		  
    	 end
    	 else begin
    	     g1 <= filter_11 && filter_12 && filter_13;
    		  g2 <= filter_21 && filter_22 && filter_23;
    		  g3 <= filter_31 && filter_32 && filter_33;
    	 end
    	 
    //clk2,每行与运算的结果再次与运算
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) 
    	     g <= 1'b0;
    
    	 else 
    	     g <= g1 && g2 && g3;
    		  	  
    assign 	Erode_data =  g ? 8'd255 : 8'd0;
    
    // 打拍做同步
    
        always @(posedge clk or  negedge rst_n) begin
            if(!rst_n)begin
                de_shift1   <=  2'b0;
    				
    				end
            else begin
                de_shift1 <= {de_shift1[0], iValid};
    				end
        end
    
        assign Erode_de   = de_shift1[1];
    
    
      endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    可看到此时窗口中九个像素进行相与操作, 下一个clk计算出g1,g2,g3,均为高电平,下一clk计算出g,为高电平,因此可输出255。同理g为低电平输出0。
    在这里插入图片描述

    六、FPGA实现膨胀

    和腐蚀相同,不同在于是进行或运算,核心代码如下:

    //clk1,进行所有行的或
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
    	      g1 <= 1'b0;
    		  g2 <= 1'b0;
    		  g3 <= 1'b0;
    		  
    	 end
    	 else begin
    	      g1 <= filter_11 || filter_12 || filter_13;
    		  g2 <= filter_21 || filter_22 || filter_23;
    		  g3 <= filter_31 || filter_32 || filter_33;
    	 end
    	 
    //clk2,每行与运算的结果再次或运算
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) 
    	     g <= 1'b0;
    
    	 else 
    	     g <= g1 || g2 || g3;
    		  
    
    	  
    assign 	Erode_data =  g ? 8'd255 : 8'd0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    FPGA实现腐蚀膨胀的效果图如下:
    左:腐蚀
    右:膨胀
    在这里插入图片描述

  • 相关阅读:
    5、Nacos服务注册服务端源码分析(四)之NotifyCenter
    Hbase容灾与备份
    17. map和set的模拟实现(也就是用红黑树封装map和set)
    vue的路由懒加载
    【开源教程6】疯壳·开源编队无人机-遥控器固件烧写
    【安卓基础6】数据存储
    dapr入门系列之前言
    PDF文件如何设置密码保护?
    【英语:基础高阶_全场景覆盖表达】K11.口语主题陈述——事物类
    【笔记】使用OrCAD对电路进行蒙特卡洛分析和最坏分析
  • 原文地址:https://blog.csdn.net/H19981118/article/details/125443947