前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于FPGA灰度图像的形态学腐蚀

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

作者头像
FPGA开源工作室
发布2019-10-29 10:53:30
7970
发布2019-10-29 10:53:30
举报
文章被收录于专栏: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的二值图像的腐蚀算法的实现

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FPGA开源工作室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档