专栏首页FPGA开源工作室基于FPGA灰度图像的形态学腐蚀

基于FPGA灰度图像的形态学腐蚀

FPGA开源工作室

FPGA/图像处理/创业/职场

关注

基于FPGA灰度图像的形态学腐蚀

01

背景知识

数学形态学是一门建立在集论基础上的学科,是几何形态学分析和描述的有力工具。数学形态学的蓬勃发展,其并行快速,易于硬件实现,目前已经在计算机视觉、信号处理与图像分析、模式识别等方面得到了极为广泛的应用。

腐蚀与膨胀是形态学滤波的两个基本运算,通过腐蚀和膨胀两种运算可以实现多种功能,主要如下:

(1) 消除噪声;

(2)分割出独立的图像元素;

(3)在图像中连接相邻的元素;

(4)寻找图像中明显的极大值和极小值区域;

(5)求出图像的梯度。

图1 腐蚀膨胀示意图

图1 a为大小为448X425像素的灰度级X射线图像;b使用半径为2个像素的圆盘形结构元对图像的腐蚀结果;c用相同的结构元对图像的膨胀结果。原图有Lixi公司提供。

形态学滤波之腐蚀

腐蚀(erode)就是求局部最小值的操作。

从数学角度来看就是将图像f和核(结构元)b进行卷积的一个过程。

当b的原点位于(x,y)处时,用一个平坦的结构元b在(x,y)处对图像f的腐蚀,定义为图像f中与b重合区域的最小值,即:

为了方便起见,将腐蚀操作记为:

(x,y)表示当前输入图像的行列坐标;

f(x,y)表示坐标点(x,y)处的图像像素值;

g(x,y)表示坐标点(x,y)处的滤波结果;

(s,t)表示作用域。

02

Matlab腐蚀源码

%%image erode

clc

clear all

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 = imerode(img_b,a);

figure,imshow(img_c);

title('img_c 3x3');

img_d = imerode(img_b,b);

figure,imshow(img_d);

title('img_d 5x5');

img_e = imerode(img_b,c);

figure,imshow(img_e);

title('img_e 7x7');

matlab形态学腐蚀效果

03

FPGA实现形态学灰度图像腐蚀

3.1 腐蚀模块的设计

1)比较子模块

2)一维形态学腐蚀子模块

3)二维形态学腐蚀子模块

(1) 比较子模块

为了代码更好的移植,我们将比较子模块设计为独立的子模块。

Erode:输出俩个数据的较小值。

(2)一维形态学腐蚀膨胀模块设计

我们要完成对nxn窗口的腐蚀或者膨胀首先我们要做图像行的一维腐蚀或膨胀。例如我们要做3x3窗口的腐蚀或膨胀,一维形态学腐蚀或膨胀如图所示:

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

Erode模块源码

/*

Module name: erode.v

Description:

*/

`timescale 1ns/1ps

module erode(

clk,

rst_n,

din,

din_valid,

dout,

dout_valid,

hs_in,

vs_in,

hs_out,

vs_out

);

parameter WIDTH = 8; // data bits is 8

parameter KSZ = 3; // window 3x3

parameter ERO_DIL = 1; //ERO_DIL = 1 erode ;ERO_DIL = 0 dilate.

parameter IMG_WIDTH = 480; //image width 480

input clk;

input rst_n;

input [WIDTH-1:0] din;

input din_valid;

output [WIDTH-1:0] dout;

output dout_valid;

input hs_in;

input vs_in;

output hs_out;

output vs_out;

wire [WIDTH-1:0] morph1d_out;

wire morph1d_data_valid;

wire [WIDTH-1:0] line_out[0:KSZ-1];

wire line_data_valid[0:KSZ-1];

wire [WIDTH-1:0] min[0:KSZ-1];

wire [WIDTH-1:0] max[0:KSZ-1];

//------------------------------------------------------------------------------------

// instantiate a one-dimensional morphology erode or dilate

//------------------------------------------------------------------------------------

morph_1d #(WIDTH,KSZ,ERO_DIL)

morph_1d_inst(

.rst_n(rst_n),

.clk(clk),

.din(din),

.hs_in(hs_in),

.vs_in(vs_in),

.hs_out(hs_out),

.vs_out(vs_out),

.din_valid(din_valid),

.dout_valid(morph1d_data_valid),

.dout(morph1d_out)

);

//------------------------------------------------------

//ERO_DIL == 1 morphology erode

//-------------------------------------------------------

generate

if(ERO_DIL == 1)

begin: xhdl0

assign min[0] = morph1d_out;

assign line_data_valid[0]= morph1d_data_valid;

genvar i;

for(i = 0; i< KSZ -1; i = i + 1)

begin :buf_line1_inst

line_buffer #(WIDTH,IMG_WIDTH,9)

line_buffer_inst(

.rst_n(rst_n),

.clk(clk),

.din(min[i]),

.dout(line_out[i+1]),

.wr_en(line_data_valid[i]),

.data_valid(line_data_valid[i+1])

);

minmax #(WIDTH,1)

minmax_i(

.clk(clk), //pixel clock

.rst_n(rst_n),

.data_valid(line_data_valid[i+1]),

.din(morph1d_out),

.din_r(line_out[i+1]),

.dout_min(min[i+1]),

.dout_max(max[i+1])

);

end

assign dout = min[KSZ-1];

assign dout_valid = line_data_valid[KSZ-1];

end

endgenerate

//-------------------------------------------------------------------

// ERO_DIL == 0 morphology dilate

//------------------------------------------------------------------

generate

if(~(ERO_DIL == 1))

begin: xhdl1

assign max[0] = morph1d_out;

assign line_data_valid[0]= morph1d_data_valid;

genvar i;

for(i = 0; i< KSZ -2; i = i + 1)

begin :buf_line1_inst

line_buffer #(WIDTH,IMG_WIDTH,9)

line_buffer_inst(

.rst_n(rst_n),

.clk(clk),

.din(max[i]),

.dout(line_out[i+1]),

.wr_en(line_data_valid[i]),

.data_valid(line_data_valid[i+1])

);

end

begin :buf_cmp_inst

minmax #(WIDTH,1)

minmax_i(

.clk(clk), //pixel clock

.rst_n(rst_n),

.data_valid(line_data_valid[i+1]),

.din(morph1d_out),

.din_r(line_out[i+1]),

.dout_min(min[i+1]),

.dout_max(max[i+1])

);

end

assign dout = max[i+1];

assign dout_valid = line_data_valid[i+1];

end

endgenerate

endmodule

形态学腐蚀结果演示

推荐阅读

基于FPGA的二值图像的腐蚀算法的实现

欢迎留言提出您宝贵的意见

本文分享自微信公众号 - FPGA开源工作室(leezym0317),作者:lee神

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • verilog常用语法二让您的FPGA设计更轻松

    一般情况下,Verilog HDL源程序中所有的行都将参加编译。但是有时希望对其中的一部分内容只有在满足条件才进行编译,也就是对一部分内容指定编译的条件,...

    FPGA开源工作室
  • 基于FPGA低通滤波器的FIR的设计

    图1 低通滤波器特征参数 如图1所示,低通滤波器的通带截止频率为ωp ,通带容限为α1,阻带截止频率为ωs,阻带容限为α2。通带定义为|ω|≤ωp ...

    FPGA开源工作室
  • 几何变换--图像裁剪

    几何变换包括:缩放、旋转、平移等。这些变换一般用于校正图像处理引起的空间失真,或者通过将图像配准到一个预定义的坐标系统中用于规范化该图像(例如,将一幅航拍图像配...

    FPGA开源工作室
  • Github 项目 - FaceBoxes高精度实时人脸检测器

    原文:Github 项目 - FaceBoxes高精度实时人脸检测器 - AIUAI

    AIHGF
  • 为Next主题添加多说评论系统

    几个月前,在好奇心的鼓动下,利用Github Pages和Hexo以及Next主题搭建一个属于自己的个人主站,由于时间伧俗,搭建成功后就没有好好完善一下,可以参...

    Jacklin999
  • 2019届网易JAVA实习2面经历

    牛客网
  • 5行代码为你的博客引入fancybox

    官方Demo code很简单,将需要处理的 img 标签放到一个有 data-fancybox="gallery" 属性的 a 标签中即可,*href* 属性配...

    码代码的陈同学
  • 动态规划:数塔问题

    动态规划问题我训练过一些题目,但是感觉自己掌握的还不是特别好! 下面以一道经典的动态规划题目说明动态规划算法的思想,文末会官方的给出对动态规划的文字叙述。

    卡尔曼和玻尔兹曼谁曼
  • 数据库|Flask实现分页显示数据

    在做网页的时候,通常会展示很多数据,如果把全部数据放在一页显示的话,会让浏览器加载变得更慢,所以通常在展示很多数据的时候进行分页显示,让浏览器进行片段式加载。先...

    算法与编程之美
  • Linux命令(39)——du命令

    (1)文件大小与占用磁盘空间大小的区别。 文件大小(又名 apparent size)是文件自身实际大小,与占用磁盘空间大小(又名 occupied spa...

    Dabelv

扫码关注云+社区

领取腾讯云代金券