Engee 文档
Notebook

形态操作,第 2 部分

在本演示中,我们将了解填充、戳和边界清理等形态操作。

首先,让我们连接必要的库。

In [ ]:
Pkg.add(["ImageBinarization", "Noise", "ImageDraw", "TestImages", "ImageMorphology"])
In [ ]:
Pkg.add("ImageBinarization")
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
In [ ]:
using Images, Noise, ImageMorphology
using ImageBinarization
using ImageDraw
using TestImages

加载图像并进行阈值处理。

In [ ]:
img_src = testimage("morphology_test_512")
Out[0]:
No description has been provided for this image
In [ ]:
img_input = binarize(Gray.(img_src), UnimodalRosin()) .> 0.5
Out[0]:
512×512 BitMatrix:
 0  0  0  0  0  0  0  0  0  0  0  0  0  …  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  …  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  …  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 ⋮              ⋮              ⋮        ⋱  ⋮              ⋮              ⋮  
 0  0  0  0  0  0  0  0  0  0  0  0  0  …  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  …  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  …  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0     0  0  0  0  0  0  0  0  0  0  0  0

我们将在后续工作中使用该图像,并将其指定为灰色阴影格式,因为下面的操作将应用于灰色格式的图像。

In [ ]:
Gray.(img_input)
Out[0]:
No description has been provided for this image

选择边框

凸壳函数输出图像最外部的类似覆盖范围的边界,并以数组 CartesianIndex 的形式返回边界对象的顶点。

In [ ]:
cordinates = convexhull(img_input)
img_convex = RGB.(copy(img_input))
push!(cordinates, cordinates[1])
draw!(img_convex, Path(cordinates), RGB(1))
img_convex
Out[0]:
No description has been provided for this image

图像填充

图像填充操作可以找到相关的图像成分,并使用它们生成图像。执行填充函数后,该图像将位于指定区间的范围内。

In [ ]:
img_noise = salt_pepper(img_input, 0.5)
fill_image_1 = imfill(img_noise, (0.1, 1))
fill_image_2 = imfill(img_noise, (0.1, 10)) # this configuration gets us best results
fill_image_3 = imfill(img_noise, (1, 10))
fill_image_4 = imfill(img_noise, (5, 20)) # objects of smaller sizes gets left out
Gray.([img_noise fill_image_1 fill_image_2 fill_image_3 fill_image_4])
Out[0]:
No description has been provided for this image

图像减薄

薄化操作采用围棋算法,决定留下哪些像素。

In [ ]:
img_thinning = thinning(img_input, algo = GuoAlgo());
Gray.([img_input img_thinning])
Out[0]:
No description has been provided for this image

边界清理

您可以使用 Clearborder 方法清除与图像边框相关的对象。

In [ ]:
cleared_img_1 = clearborder(img_input, 20); # 20 is the width of border that's examined
cleared_img_2 = clearborder(img_input, 30); # notice how it remove the inner circle even if it's outside its range
cleared_img_3 = clearborder(img_input, 30, 1);

移除的默认颜色是 0,即移除 RGB(0),但现在因为是 1,所以会清除整个图像,这是因为采用了填充算法。

In [ ]:
Gray.([img_input cleared_img_1 cleared_img_2 cleared_img_3])
Out[0]:
No description has been provided for this image

结论

在本示例中,我们分解了一些可用于图像的有用形态学操作。