|
| 1 | +#= |
| 2 | +# Fuzzy edge detector |
| 3 | +
|
| 4 | +This tutorial shows how fuzzy logic can be applied to image processing. It showcases how |
| 5 | +`FuzzyLogic.jl` seamlessly composes with common Julia image processing libraries and works |
| 6 | +out-of-the box. |
| 7 | +
|
| 8 | +This tutorial builds a fuzzy edge detector and it is inspired from the matlab tutorial |
| 9 | +available [here](https://www.mathworks.com/help/fuzzy/fuzzy-logic-image-processing.html). |
| 10 | +
|
| 11 | +DOWNLOAD_NOTE |
| 12 | +
|
| 13 | +## Introduction |
| 14 | +
|
| 15 | +We want to design an edge detector. That is, a function that takes an image as input and finds |
| 16 | +the edges in the image. |
| 17 | +Our function should produce a new image, with edges highlighted in black and flat areas in white. |
| 18 | +
|
| 19 | +First, let's load the image processing tools we need in this tutorial. |
| 20 | +=# |
| 21 | + |
| 22 | +using TestImages, ImageFiltering, ImageShow, ImageCore |
| 23 | + |
| 24 | +img = Gray.(testimage("house")) |
| 25 | + |
| 26 | +#= |
| 27 | +Next, we need to model our problem. When we cross an edge, we have a transition from a clearly delimited area to another. |
| 28 | +Hence, a pixel is on an edge if moving in its neighborhood we see some change in intensity. |
| 29 | +If, on the other hand, in the pixel neighborhood there is no change, then it belongs to a flat area. |
| 30 | +
|
| 31 | +Hence, to detect edges we need to compute the gradient of the image at each pixel. |
| 32 | +This can be done using `imgradients` from [ImageFiltering](https://github.com/JuliaImages/ImageFiltering.jl). |
| 33 | +This function will return two images, one containg the gradient x-component at each pixel, and one containing the y-component at each pixel. |
| 34 | +For better visualization, these gradient images are renormalized so that their maximum in absolute value is ``1``. |
| 35 | +=# |
| 36 | + |
| 37 | +img_y, img_x = imgradients(img, KernelFactors.sobel) |
| 38 | + |
| 39 | +img_y /= Float64(maximum(abs.(img_y))) |
| 40 | +img_x /= Float64(maximum(abs.(img_x))) |
| 41 | + |
| 42 | +img_y |
| 43 | +#- |
| 44 | +img_x |
| 45 | + |
| 46 | +#= |
| 47 | +## Fuzzy system design |
| 48 | +
|
| 49 | +Now we want to design a fuzzy system that takes as input the gradient x- and y- components and produces as output the intensity of the new image. |
| 50 | +Particularly, in the output image we want to plot flat areas in white (intensity close to ``1``) and edges in black (intensity close to ``0``). |
| 51 | +
|
| 52 | +Based on our previous discussion, a pixel belongs to a flat area if it has zero gradient (i.e. both x- and y-components are zero). |
| 53 | +If the gradient is non-zero (either x- or y-component is non-zero) then it belongs to an edge. |
| 54 | +Hence for our fuzzy edge detector we can use the following rules |
| 55 | +
|
| 56 | +- If the gradient x-component is zero and the gradient y-component is zero, then the output intensity is white. |
| 57 | +- If the gradient x-component is nonzero or the gradient y-compnent is non-zero, then the output intensity is black. |
| 58 | +
|
| 59 | +Hence, for the input, we will use a single membership function `zero`, which is a sharp Gaussian centered at zero. |
| 60 | +For the outupt, we have two membership functions, `black` and `white`. |
| 61 | +Recalling that a black pixel means intensity zero and a white pixel intensity one, we will use for `black` a linear membership function, that decreases from ``1`` |
| 62 | +to ``0`` as the intensity increases. Similarly, for `white` we can use a linear membership function that increases as the intensity increases. |
| 63 | +
|
| 64 | +We can now implement and visualize our inference system. |
| 65 | +=# |
| 66 | + |
| 67 | +using FuzzyLogic, Plots |
| 68 | + |
| 69 | +fis = @mamfis function edge_detector(dx, dy)::Iout |
| 70 | + dx := begin |
| 71 | + domain = -1:1 |
| 72 | + zero = GaussianMF(0.0, 0.1) |
| 73 | + end |
| 74 | + |
| 75 | + dy := begin |
| 76 | + domain = -1:1 |
| 77 | + zero = GaussianMF(0.0, 0.1) |
| 78 | + end |
| 79 | + |
| 80 | + Iout := begin |
| 81 | + domain = 0:1 |
| 82 | + black = LinearMF(0.7, 0.0) |
| 83 | + white = LinearMF(0.1, 1.0) |
| 84 | + end |
| 85 | + |
| 86 | + dx == zero && dy == zero --> Iout == white |
| 87 | + dx != zero || dy != zero --> Iout == black |
| 88 | +end |
| 89 | +plot(fis) |
| 90 | + |
| 91 | +#- |
| 92 | + |
| 93 | +plot(plot(fis, :dx), plot(fis, :Iout), layout = (1, 2)) |
| 94 | + |
| 95 | +#= |
| 96 | +We are now ready to apply our fuzzy edge detector to the input image. |
| 97 | +We will create a new image `Iout` and assign to each pixel the intensity value computed with our fuzzy system. |
| 98 | +=# |
| 99 | +Iout = copy(img) |
| 100 | + |
| 101 | +for idx in eachindex(Iout) |
| 102 | + Iout[idx] = fis(dx = img_x[idx], dy = img_y[idx])[:Iout] |
| 103 | +end |
| 104 | +Iout |
0 commit comments