Skip to content

Commit f046831

Browse files
new demo: Canny operator (rework #177) (#183)
Co-authored-by: Ashwani Rathee <[email protected]>
1 parent 4749786 commit f046831

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
2424
IndirectArrays = "9b13fd28-a010-5f03-acff-a1bbcff69959"
2525
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
2626
MosaicViews = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"
27+
Noise = "81d43f40-5267-43b7-ae1c-8b967f377efa"
2728
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
2829
PaddedViews = "5432bcbf-9aad-5242-b902-cca2824c8663"
2930
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
@@ -57,6 +58,7 @@ Images = "0.23"
5758
IndirectArrays = "0"
5859
MappedArrays = "0"
5960
MosaicViews = "0"
61+
Noise = "0.2"
6062
OffsetArrays = "1.0"
6163
PaddedViews = "0"
6264
Rotations = "1"
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# ---
2+
# cover: assets/canny.gif
3+
# title: Canny Edge Detection
4+
# author: Ashwani Rathee; Johnny Chen
5+
# date: 2021-3-20
6+
# ---
7+
8+
# Canny filter is still a powerful edge detector even though it's invented in 1986 [1].
9+
# This demo shows you how to use our newly developed package `ImageEdgeDetection` with
10+
# Canny filter as an example.
11+
12+
using Images, ImageEdgeDetection, Noise
13+
using ImageEdgeDetection: Percentile
14+
using TestImages
15+
16+
# !!! info
17+
# `ImageEdgeDetection.jl` rewrites many functions which previously exists in `Images.jl` and
18+
# will be reexported in `Images` in the future, so you don't need to `using ImageEdgeDetection`
19+
# explicitly after that.
20+
21+
# In JuliaImages, any `AbstractArray` can be treated as an image. In this demo, we'll use a generated
22+
# image for illustration purpose.
23+
24+
# First, we create our test image.
25+
26+
function make_simple_image(sz)
27+
img_gray = zeros(Gray{Float64}, sz...)
28+
fill_region = map(x->x÷4:3x÷4, sz)
29+
img_gray[fill_region...] .= 1
30+
img_rot = imrotate(img_gray, pi/4)
31+
32+
## Corrupt the image with blur and noise, it makes our canny edge detection
33+
## function works a little harder since the canny filter is based on the idea
34+
## of finding gradients.
35+
img_gauss = imfilter(img_rot, Kernel.gaussian(2))
36+
37+
## We use `salt_pepper` filter from `Noise.jl`. Salt-and-pepper noise in general
38+
## is a noise that modifies a pixel with two different values of noise.
39+
## Here we only random set pixels to white.
40+
img_noise = salt_pepper(img_gauss, 0.05, salt_prob = 0, pepper = 0.9)
41+
end
42+
img = make_simple_image((200, 200))
43+
44+
# `ImageEdgeDetection` offers a unified API `detect_edges(img, alg)` with
45+
# various algorithms. In this demo we'll show how to use the `Canny`
46+
# operator [1]. First we'll need to create an algorithm instance of `Canny`.
47+
48+
alg = Canny(spatial_scale=1, high=Percentile(80), low=Percentile(20))
49+
50+
# and then apply this instance as parameters to `detect_edges`, with the Julia
51+
# [multiple dispatch mechanism](https://docs.julialang.org/en/v1/manual/methods/#Methods),
52+
# `detect_edges` knows which algorithm implementation should be called with
53+
# the `alg` information.
54+
55+
edges = detect_edges(img, alg)
56+
mosaicview(img, edges; nrow=1)
57+
58+
# Now let's see how different Canny parameters changes the result, and also see
59+
# how it works on real world images:
60+
61+
cameraman = testimage("cameraman")
62+
canny(σ) = Canny(spatial_scale=σ, high=Percentile(80), low=Percentile(20))
63+
simple_results = map->detect_edges(img, canny(σ)), 1:5)
64+
cameraman_results = map->detect_edges(cameraman, canny(σ)), 1:5)
65+
66+
mosaicview(
67+
mosaicview(img, cameraman),
68+
map(mosaicview, simple_results, cameraman_results)...;
69+
nrow=1
70+
)
71+
72+
# As you can see, higher `spatial_scale` tells the Canny operator to ignore small
73+
# details and thus gives a "clean" edge result; whether it is a correct/useful edge
74+
# result depends on how you interpret it.
75+
76+
save("assets/canny.gif", cat(cameraman, cameraman_results...; dims=3); fps=2) #src
77+
78+
# # References
79+
80+
# [1] J. Canny, "A Computational Approach to Edge Detection," in _IEEE Transactions on Pattern Analysis and Machine Intelligence_, vol.
81+
# PAMI-8, no. 6, pp. 679-698, Nov. 1986, doi: 10.1109/TPAMI.1986.4767851.

0 commit comments

Comments
 (0)