|
| 1 | +# --- |
| 2 | +# cover: assets/lbp.gif |
| 3 | +# title: Local Binary Patterns |
| 4 | +# description: This demo shows how to use the LBP algorithm to extract features from images. |
| 5 | +# author: Ashwani Rathee |
| 6 | +# date: 2021-07-25 |
| 7 | +# --- |
| 8 | + |
| 9 | +# In this demonstration, we show how local binary patterns (LBP) could be |
| 10 | +# used as a very efficient texture classifier. |
| 11 | + |
| 12 | +# LBP operator labels the pixels of an image by thresholding the neighborhood |
| 13 | +# of each pixel and considers the result as a binary number. |
| 14 | +# LBP feature vector would assign value to neighboring based on whether |
| 15 | +# the neighboring cells have values higher/lower than threshold(equal to central cell value) |
| 16 | +# in a grayscale image. |
| 17 | + |
| 18 | +#  |
| 19 | + |
| 20 | +# Local binary patterns calculation: |
| 21 | +# |
| 22 | +# - Divide the examined window into cells (e.g. `16x16` pixels for each cell). |
| 23 | +# - For each pixel in a cell, compare the pixel to each of its `8` neighbors (on its |
| 24 | +# left-top, left-middle, left-bottom, right-top, etc.). Follow the pixels along a circle, |
| 25 | +# i.e. clockwise or counterclockwise. |
| 26 | +# - In the above step, the neighbours considered can be changed by varying the radius of the |
| 27 | +# circle around the pixel, R and the quantisation of the angular space P. |
| 28 | +# - Where the center pixel's value is greater than the neighbor's value, write "0". |
| 29 | +# Otherwise, write "1". This gives an 8-digit binary number (which is usually converted to |
| 30 | +# decimal for convenience). |
| 31 | +# - Compute the `histogram`, over the cell, of the frequency of each "number" occurring |
| 32 | +# (i.e., each combination of which pixels are smaller and which are greater than the |
| 33 | +# center). This histogram can be seen as a 256-dimensional feature vector. |
| 34 | +# - Optionally normalize the `histogram`. |
| 35 | +# - Concatenate (normalized) histograms of all cells. This gives a feature vector for the |
| 36 | +# entire window. |
| 37 | + |
| 38 | +#  |
| 39 | +# Above example shows the LBP(P,R) calculation on the grayscale image. |
| 40 | + |
| 41 | +# The output from step 4 is stored in corresponding cell of the resultant array. |
| 42 | +# The feature vector can now then be processed using some machine-learning |
| 43 | +# algorithm to classify images. |
| 44 | +# Such classifiers are often used for face recognition or texture analysis. |
| 45 | + |
| 46 | +# Now let's explore local binary patterns using ImageFeatures.jl |
| 47 | + |
| 48 | +using ImageFeatures |
| 49 | +using Images, TestImages |
| 50 | + |
| 51 | +# The first step in constructing the LBP texture descriptor is to get a grayscale image, in this |
| 52 | +# example we use the house image. |
| 53 | + |
| 54 | +img = restrict(Gray.(testimage("house"))) # size 256*256 house image |
| 55 | + |
| 56 | +# For each pixel in the grayscale image, we select a neighborhood of size `r` surrounding the |
| 57 | +# center pixel. A LBP value is then calculated for this center pixel and stored in the output |
| 58 | +# 2D array with the same width and height as the input image. |
| 59 | + |
| 60 | +# Now let's calculate local binary pattern output using the `lbp` function API in which we |
| 61 | +# have to specify the `method`, `points`,`radius`. There are several different LBP methods |
| 62 | +# available in `ImageFeatures.jl` e.g., `lbp_original`, `lbp_uniform` and |
| 63 | +# `lbp_rotation_invariant` but we will use original LBP here. |
| 64 | +# - `points`: The number of points p in a circularly symmetric neighborhood to consider |
| 65 | +# (thus removing relying on a square neighborhood). |
| 66 | +# - `radius`: The radius of the circle `r`, which allows us to account for different scales. |
| 67 | + |
| 68 | +img_lbp = lbp(img, 8, 3, lbp_original); # use the original LBP implementation |
| 69 | +img_lbp = @. Gray.(img_lbp / 255.0) # convert to normalized gray image |
| 70 | +edges, counts = build_histogram(img_lbp, 25, minval = 0, maxval = 1); |
| 71 | +## plot(edges[1:end-1], counts[1:end-1]; title="LBP vs No. of Occurences", xlabel="Normalized LBP values", ylabel="Number of occurences") |
| 72 | + |
| 73 | +#  |
| 74 | + |
| 75 | +# Using these edges and counts, we can create a graph which gives us insight into local binary patterns |
| 76 | +# output. Local binary patterns gives us a clue to corners, flat and edges in a image. |
| 77 | +# There are 5 peaks in this graph and these can classified into these types: |
| 78 | +# - Corner : Peaks around `x=0.2` and `x=0.7` |
| 79 | +# - Edge : Peak in center around `x=0.5` |
| 80 | +# - Flat : Peaks near `x=0.0` and `x=1.0` |
| 81 | + |
| 82 | +mosaicview(img, img_lbp; nrow = 1, rowmajor = true) |
| 83 | + |
| 84 | +save("assets/lbp.gif", cat(img, img_lbp; dims = 3); fps = 1) #src |
| 85 | + |
| 86 | +# # Reference: |
| 87 | +# - [Local Binary Patterns - Wikipedia article](https://en.wikipedia.org/wiki/Local_binary_patterns) |
| 88 | +# - [Local Binary Patterns - ScholarPedia article](http://www.scholarpedia.org/article/Local_Binary_Patterns) |
0 commit comments