基于FPGA灰度圖像的形態(tài)學(xué)腐蝕
掃描二維碼
隨時(shí)隨地手機(jī)看文章
基于FPGA灰度圖像的形態(tài)學(xué)腐蝕
01
背景知識(shí)
數(shù)學(xué)形態(tài)學(xué)是一門建立在集論基礎(chǔ)上的學(xué)科,是幾何形態(tài)學(xué)分析和描述的有力工具。數(shù)學(xué)形態(tài)學(xué)的蓬勃發(fā)展,其并行快速,易于硬件實(shí)現(xiàn),目前已經(jīng)在計(jì)算機(jī)視覺、信號(hào)處理與圖像分析、模式識(shí)別等方面得到了極為廣泛的應(yīng)用。
腐蝕與膨脹是形態(tài)學(xué)濾波的兩個(gè)基本運(yùn)算,通過腐蝕和膨脹兩種運(yùn)算可以實(shí)現(xiàn)多種功能,主要如下:
(1) 消除噪聲;
(2)分割出獨(dú)立的圖像元素;
(3)在圖像中連接相鄰的元素;
(4)尋找圖像中明顯的極大值和極小值區(qū)域;
(5)求出圖像的梯度。
圖1 腐蝕膨脹示意圖
圖1 a為大小為448X425像素的灰度級(jí)X射線圖像;b使用半徑為2個(gè)像素的圓盤形結(jié)構(gòu)元對(duì)圖像的腐蝕結(jié)果;c用相同的結(jié)構(gòu)元對(duì)圖像的膨脹結(jié)果。原圖有Lixi公司提供。
形態(tài)學(xué)濾波之腐蝕
腐蝕(erode)就是求局部最小值的操作。
從數(shù)學(xué)角度來看就是將圖像f和核(結(jié)構(gòu)元)b進(jìn)行卷積的一個(gè)過程。
當(dāng)b的原點(diǎn)位于(x,y)處時(shí),用一個(gè)平坦的結(jié)構(gòu)元b在(x,y)處對(duì)圖像f的腐蝕,定義為圖像f中與b重合區(qū)域的最小值,即:
為了方便起見,將腐蝕操作記為:
(x,y)表示當(dāng)前輸入圖像的行列坐標(biāo);
f(x,y)表示坐標(biāo)點(diǎn)(x,y)處的圖像像素值;
g(x,y)表示坐標(biāo)點(diǎn)(x,y)處的濾波結(jié)果;
(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形態(tài)學(xué)腐蝕效果
03
FPGA實(shí)現(xiàn)形態(tài)學(xué)灰度圖像腐蝕
3.1 腐蝕模塊的設(shè)計(jì)
1)比較子模塊
2)一維形態(tài)學(xué)腐蝕子模塊
3)二維形態(tài)學(xué)腐蝕子模塊
(1) 比較子模塊
為了代碼更好的移植,我們將比較子模塊設(shè)計(jì)為獨(dú)立的子模塊。
Erode:輸出倆個(gè)數(shù)據(jù)的較小值。
(2)一維形態(tài)學(xué)腐蝕膨脹模塊設(shè)計(jì)
我們要完成對(duì)nxn窗口的腐蝕或者膨脹首先我們要做圖像行的一維腐蝕或膨脹。例如我們要做3x3窗口的腐蝕或膨脹,一維形態(tài)學(xué)腐蝕或膨脹如圖所示:
(3) 二維形態(tài)學(xué)腐蝕與膨脹子模塊設(shè)計(jì)
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
形態(tài)學(xué)腐蝕結(jié)果演示