質(zhì)量聲明:原創(chuàng)文章,內(nèi)容質(zhì)量問(wèn)題請(qǐng)?jiān)u論吐槽。如對(duì)您產(chǎn)生干擾,可私信刪除。
主要參考:(美)拉斐爾·C.岡薩雷斯. 數(shù)字圖像處理 第3版[M]. 阮秋琦,譯. 北京:電子工業(yè)出版社, 2017: 633.
形態(tài)學(xué)重建
形態(tài)學(xué)重建涉及兩幅圖像和一個(gè)結(jié)構(gòu)元:
- Marker 圖像 :包含變換的起點(diǎn),將被連續(xù)膨脹,直至收斂
- Mask 圖像 :用來(lái)約束膨脹結(jié)果,即 Mask >= Marker
- 結(jié)構(gòu)單元 (Structuring Element,SE):定義連通性
數(shù)學(xué)迭代式:
M a r k e r = ( M a r k e r ⊕ S E ) ∩ M a s k Marker = (Marker \oplus SE) \cap Mask
M
a
r
k
e
r
=
(
M
a
r
k
e
r
⊕
S
E
)
∩
M
a
s
k
代碼示例:
def
imreconstruct
(
marker
,
mask
,
SE
=
np
.
ones
(
[
3
,
3
]
)
)
:
"""
描述:以mask為約束,連續(xù)膨脹marker,實(shí)現(xiàn)形態(tài)學(xué)重建,其中mask >= marker
參數(shù):
- marker 標(biāo)記圖像,單通道/三通道圖像
- mask 模板圖像,與marker同型
- conn 聯(lián)通性重建結(jié)構(gòu)元,參照matlab::imreconstruct::conn參數(shù),默認(rèn)為8聯(lián)通
"""
while
True
:
marker_pre
=
marker
dilation
=
cv
.
dilate
(
marker
,
kernel
=
SE
)
marker
=
np
.
min
(
(
dilation
,
mask
)
,
axis
=
0
)
if
(
marker_pre
==
marker
)
.
all
(
)
:
break
return
marker
孔洞填充
孔洞定義:被前景(白色)連通域包圍的封閉的背景(黑色)區(qū)域,不限于圓形。如圖所示。
原理:
以原圖像的補(bǔ)集作為Mask,用來(lái)限制膨脹結(jié)果;以帶有白色邊框的黑色圖像為初始Marker,用SE對(duì)其進(jìn)行連續(xù)膨脹,直至收斂;最后對(duì)Marker取補(bǔ)即得到最終圖像,與原圖相減可得到填充圖像。
M a r k e r ( x , y ) = { 255 , ( x , y ) ∈ B o u n d a r y 0 , o t h e r s Marker(x, y) = \left\{\begin{matrix} 255 & , & (x,y) \in Boundary\\ 0 & , & others \end{matrix}\right. M a r k e r ( x , y ) = { 2 5 5 0 ? , , ? ( x , y ) ∈ B o u n d a r y o t h e r s ?
代碼示例:
import
numpy
as
np
import
cv2
as
cv
from
matplotlib
import
pyplot
as
plt
img
=
cv
.
imread
(
"text.jpg"
)
# 二值化
imgray
=
cv
.
cvtColor
(
img
,
cv
.
COLOR_BGR2GRAY
)
imgray
[
imgray
<
100
]
=
0
imgray
[
imgray
>=
100
]
=
255
# 原圖取補(bǔ)得到MASK圖像
mask
=
255
-
imgray
# 構(gòu)造Marker圖像
marker
=
np
.
zeros_like
(
imgray
)
marker
[
0
,
:
]
=
255
marker
[
-
1
,
:
]
=
255
marker
[
:
,
0
]
=
255
marker
[
:
,
-
1
]
=
255
marker_0
=
marker
.
copy
(
)
# 形態(tài)學(xué)重建
SE
=
cv
.
getStructuringElement
(
shape
=
cv
.
MORPH_CROSS
,
ksize
=
(
3
,
3
)
)
while
True
:
marker_pre
=
marker
dilation
=
cv
.
dilate
(
marker
,
kernel
=
SE
)
marker
=
np
.
min
(
(
dilation
,
mask
)
,
axis
=
0
)
if
(
marker_pre
==
marker
)
.
all
(
)
:
break
dst
=
255
-
marker
filling
=
dst
-
imgray
# 顯示
plt
.
figure
(
figsize
=
(
12
,
6
)
)
# width * height
plt
.
subplot
(
2
,
3
,
1
)
,
plt
.
imshow
(
imgray
,
cmap
=
'gray'
)
,
plt
.
title
(
'src'
)
,
plt
.
axis
(
"off"
)
plt
.
subplot
(
2
,
3
,
2
)
,
plt
.
imshow
(
mask
,
cmap
=
'gray'
)
,
plt
.
title
(
'Mask'
)
,
plt
.
axis
(
"off"
)
plt
.
subplot
(
2
,
3
,
3
)
,
plt
.
imshow
(
marker_0
,
cmap
=
'gray'
)
,
plt
.
title
(
'Marker 0'
)
,
plt
.
axis
(
"off"
)
plt
.
subplot
(
2
,
3
,
4
)
,
plt
.
imshow
(
marker
,
cmap
=
'gray'
)
,
plt
.
title
(
'Marker'
)
,
plt
.
axis
(
"off"
)
plt
.
subplot
(
2
,
3
,
5
)
,
plt
.
imshow
(
dst
,
cmap
=
'gray'
)
,
plt
.
title
(
'dst'
)
,
plt
.
axis
(
"off"
)
plt
.
subplot
(
2
,
3
,
6
)
,
plt
.
imshow
(
filling
,
cmap
=
'gray'
)
,
plt
.
title
(
'Holes'
)
,
plt
.
axis
(
"off"
)
plt
.
show
(
)
選用不同尺寸的SE,進(jìn)行填充對(duì)比:ksize=3x3(左),ksize=7x7(右)
由此可見(jiàn), 如果選擇的結(jié)構(gòu)單元過(guò)大,膨脹操作會(huì)越過(guò)邊界,膨脹到孔洞中,導(dǎo)致部分孔洞填充失敗。就本例來(lái)看3x3的SE可以做到準(zhǔn)確填充。
并且,對(duì)于大小不一的孔洞,3x3的SE同樣可以做到準(zhǔn)確填充。如圖所示:
注: 關(guān)于孔洞填充的其他問(wèn)題,可以參考博文 形態(tài)學(xué)填充孔洞的幾個(gè)問(wèn)題
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
