|
| 1 | +# --- |
| 2 | +# cover: assets/convex_hull.gif |
| 3 | +# title: Convex Hull, Filling, Thinning, ClearBorder |
| 4 | +# author: Ashwani Rathee |
| 5 | +# date: 2021-7-4 |
| 6 | +# --- |
| 7 | + |
| 8 | +# In this demonstration, we will be covering morphological operations like |
| 9 | +# convexhull, image thinning, hole filling and border clearing. |
| 10 | + |
| 11 | +using Images, Noise, ImageMorphology |
| 12 | +using ImageBinarization |
| 13 | +using ImageDraw |
| 14 | +using TestImages |
| 15 | + |
| 16 | +img_src = testimage("morphology_test_512") |
| 17 | + |
| 18 | +# Thresholding of image |
| 19 | + |
| 20 | +img_input = binarize(Gray.(img_src), UnimodalRosin()) .> 0.5 |
| 21 | + |
| 22 | +# This is the image that we will be using throughout this demonstration |
| 23 | +# in its boolean form as below mentioned operations are applied on binary images. |
| 24 | + |
| 25 | +Gray.(img_input) |
| 26 | + |
| 27 | +# ## Convex Hull |
| 28 | + |
| 29 | +# Convex Hull operation outputs outer most cover-like boundary of a binary image and |
| 30 | +# returns the vertices of convex hull as a CartesianIndex array. |
| 31 | + |
| 32 | +cordinates = convexhull(img_input) |
| 33 | +img_convex = RGB.(copy(img_input)) |
| 34 | +push!(cordinates, cordinates[1]) |
| 35 | +draw!(img_convex, Path(cordinates), RGB(1)) |
| 36 | +img_convex |
| 37 | + |
| 38 | +# ## Image Filling |
| 39 | + |
| 40 | +# Image filling operation finds connected components of an image using `flood-fill |
| 41 | +# algorithm` and operation gives result image after filling objects that falls in the |
| 42 | +# range of interval specified. |
| 43 | + |
| 44 | +# For filling objects, represent the holes(part to be filled) with `true` in your array. Meaning color RGB(1)/black |
| 45 | + |
| 46 | +# `imfill(img, interval, value, connectivity)` require a `boolean` array, `interval` is a tuple `(a,b)` that specifies the |
| 47 | +# range of values to be filled, the objects of size in this range will be filled with `false` . `connectivity` |
| 48 | +# takes the same values as in label_components (Default value is `1:ndims(img)``) |
| 49 | + |
| 50 | +img_noise = salt_pepper(img_input, 0.5) |
| 51 | +fill_image_1 = imfill(img_noise, (0.1, 1)) |
| 52 | +fill_image_2 = imfill(img_noise, (0.1, 10)) # this configuration gets us best results |
| 53 | +fill_image_3 = imfill(img_noise, (1, 10)) |
| 54 | +fill_image_4 = imfill(img_noise, (5, 20)) # objects of smaller sizes gets left out |
| 55 | +Gray.([img_noise fill_image_1 fill_image_2 fill_image_3 fill_image_4]) |
| 56 | + |
| 57 | +# ## Image thinning |
| 58 | + |
| 59 | +# Thinning operation applies a binary blob thinning operation to achieve a skeletization of the input image. |
| 60 | +# Guo Algorithm, decides which pixels to keep and which to remove using 3 rules given in original paper. |
| 61 | + |
| 62 | +img_thinning = thinning(img_input, algo = GuoAlgo()); |
| 63 | +Gray.([img_input img_thinning]) |
| 64 | + |
| 65 | +# ## Clear Border |
| 66 | + |
| 67 | +# Clearborder method can be used to clear objects connected to the border of the image. |
| 68 | + |
| 69 | +# `clearborder(img, width, background)` can be used upon binary/grayscale input image |
| 70 | +# on a `width` pixel wide border(`Default is 1 pixel`). `background` is the value that is given |
| 71 | +# to pixels that are cleared(`Default is 0, black color`) |
| 72 | + |
| 73 | +cleared_img_1 = clearborder(img_input, 20); # 20 is the width of border that's examined |
| 74 | +cleared_img_2 = clearborder(img_input, 30); # notice how it remove the inner circle even if it's outside its range |
| 75 | +cleared_img_3 = clearborder(img_input, 30, 1); |
| 76 | +# Default color for removal is 0 meaning remove `RGB(0)` but now since it's 1 it's clears the whole image due to flood fill algorithm |
| 77 | +Gray.([img_input cleared_img_1 cleared_img_2 cleared_img_3]) |
| 78 | + |
| 79 | +save("assets/convex_hull.gif", cat(img_input, cleared_img_1, cleared_img_2, cleared_img_3; dims=3); fps=2) #src |
0 commit comments