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
形态学腐蚀结果演示
NEWS
◆
推荐阅读
◆
本文分享自微信公众号 - FPGA开源工作室(leezym0317)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/4579395/blog/4636469