Skip to content

Commit b1818af

Browse files
zhexuanlgithub-actionscclauss
authored
Add Digital Image Processing Algorithm: Local Binary Pattern (TheAlgorithms#6294)
* add algorithm local binary pattern * fix failed test for local binary pattern * updating DIRECTORY.md * fix detected precommit-error * fix precommit error * final check * Add descriptive name for parameters x and y * Update digital_image_processing/filters/local_binary_pattern.py Co-authored-by: Christian Clauss <[email protected]> * Update digital_image_processing/filters/local_binary_pattern.py Co-authored-by: Christian Clauss <[email protected]> * Update digital_image_processing/filters/local_binary_pattern.py Co-authored-by: Christian Clauss <[email protected]> * Update local_binary_pattern.py * undo changes made on get_neighbors_pixel() * files formatted by black * Update digital_image_processing/filters/local_binary_pattern.py ok thanks Co-authored-by: Christian Clauss <[email protected]> * add test for get_neighbors_pixel() function * reviewed * fix get_neighbors_pixel * Update test_digital_image_processing.py * updating DIRECTORY.md * Create code_quality.yml * Create code_quality.yml * Delete code_quality.yml * Update code_quality.yml * Delete code_quality.yml Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss <[email protected]>
1 parent f31fa4e commit b1818af

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

DIRECTORY.md

+2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
* [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py)
153153
* [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py)
154154
* [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py)
155+
* [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py)
155156
* [Merge Two Binary Trees](data_structures/binary_tree/merge_two_binary_trees.py)
156157
* [Non Recursive Segment Tree](data_structures/binary_tree/non_recursive_segment_tree.py)
157158
* [Number Of Possible Binary Trees](data_structures/binary_tree/number_of_possible_binary_trees.py)
@@ -229,6 +230,7 @@
229230
* [Convolve](digital_image_processing/filters/convolve.py)
230231
* [Gabor Filter](digital_image_processing/filters/gabor_filter.py)
231232
* [Gaussian Filter](digital_image_processing/filters/gaussian_filter.py)
233+
* [Local Binary Pattern](digital_image_processing/filters/local_binary_pattern.py)
232234
* [Median Filter](digital_image_processing/filters/median_filter.py)
233235
* [Sobel Filter](digital_image_processing/filters/sobel_filter.py)
234236
* Histogram Equalization
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import cv2
2+
import numpy as np
3+
4+
5+
def get_neighbors_pixel(
6+
image: np.ndarray, x_coordinate: int, y_coordinate: int, center: int
7+
) -> int:
8+
"""
9+
Comparing local neighborhood pixel value with threshold value of centre pixel.
10+
Exception is required when neighborhood value of a center pixel value is null.
11+
i.e. values present at boundaries.
12+
13+
:param image: The image we're working with
14+
:param x_coordinate: x-coordinate of the pixel
15+
:param y_coordinate: The y coordinate of the pixel
16+
:param center: center pixel value
17+
:return: The value of the pixel is being returned.
18+
"""
19+
20+
try:
21+
return int(image[x_coordinate][y_coordinate] >= center)
22+
except (IndexError, TypeError):
23+
return 0
24+
25+
26+
def local_binary_value(image: np.ndarray, x_coordinate: int, y_coordinate: int) -> int:
27+
"""
28+
It takes an image, an x and y coordinate, and returns the
29+
decimal value of the local binary patternof the pixel
30+
at that coordinate
31+
32+
:param image: the image to be processed
33+
:param x_coordinate: x coordinate of the pixel
34+
:param y_coordinate: the y coordinate of the pixel
35+
:return: The decimal value of the binary value of the pixels
36+
around the center pixel.
37+
"""
38+
center = image[x_coordinate][y_coordinate]
39+
powers = [1, 2, 4, 8, 16, 32, 64, 128]
40+
41+
# skip get_neighbors_pixel if center is null
42+
if center is None:
43+
return 0
44+
45+
# Starting from the top right, assigning value to pixels clockwise
46+
binary_values = [
47+
get_neighbors_pixel(image, x_coordinate - 1, y_coordinate + 1, center),
48+
get_neighbors_pixel(image, x_coordinate, y_coordinate + 1, center),
49+
get_neighbors_pixel(image, x_coordinate - 1, y_coordinate, center),
50+
get_neighbors_pixel(image, x_coordinate + 1, y_coordinate + 1, center),
51+
get_neighbors_pixel(image, x_coordinate + 1, y_coordinate, center),
52+
get_neighbors_pixel(image, x_coordinate + 1, y_coordinate - 1, center),
53+
get_neighbors_pixel(image, x_coordinate, y_coordinate - 1, center),
54+
get_neighbors_pixel(image, x_coordinate - 1, y_coordinate - 1, center),
55+
]
56+
57+
# Converting the binary value to decimal.
58+
return sum(
59+
binary_value * power for binary_value, power in zip(binary_values, powers)
60+
)
61+
62+
63+
if __name__ == "main":
64+
65+
# Reading the image and converting it to grayscale.
66+
image = cv2.imread(
67+
"digital_image_processing/image_data/lena.jpg", cv2.IMREAD_GRAYSCALE
68+
)
69+
70+
# Create a numpy array as the same height and width of read image
71+
lbp_image = np.zeros((image.shape[0], image.shape[1]))
72+
73+
# Iterating through the image and calculating the
74+
# local binary pattern value for each pixel.
75+
for i in range(0, image.shape[0]):
76+
for j in range(0, image.shape[1]):
77+
lbp_image[i][j] = local_binary_value(image, i, j)
78+
79+
cv2.imshow("local binary pattern", lbp_image)
80+
cv2.waitKey(0)
81+
cv2.destroyAllWindows()

digital_image_processing/test_digital_image_processing.py

+32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
PyTest's for Digital Image Processing
33
"""
4+
import numpy as np
45
from cv2 import COLOR_BGR2GRAY, cvtColor, imread
56
from numpy import array, uint8
67
from PIL import Image
@@ -12,6 +13,7 @@
1213
from digital_image_processing.edge_detection import canny as canny
1314
from digital_image_processing.filters import convolve as conv
1415
from digital_image_processing.filters import gaussian_filter as gg
16+
from digital_image_processing.filters import local_binary_pattern as lbp
1517
from digital_image_processing.filters import median_filter as med
1618
from digital_image_processing.filters import sobel_filter as sob
1719
from digital_image_processing.resize import resize as rs
@@ -91,3 +93,33 @@ def test_nearest_neighbour(
9193
nn = rs.NearestNeighbour(imread(file_path, 1), 400, 200)
9294
nn.process()
9395
assert nn.output.any()
96+
97+
98+
def test_local_binary_pattern():
99+
file_path: str = "digital_image_processing/image_data/lena.jpg"
100+
101+
# Reading the image and converting it to grayscale.
102+
image = imread(file_path, 0)
103+
104+
# Test for get_neighbors_pixel function() return not None
105+
x_coordinate = 0
106+
y_coordinate = 0
107+
center = image[x_coordinate][y_coordinate]
108+
109+
neighbors_pixels = lbp.get_neighbors_pixel(
110+
image, x_coordinate, y_coordinate, center
111+
)
112+
113+
assert neighbors_pixels is not None
114+
115+
# Test for local_binary_pattern function()
116+
# Create a numpy array as the same height and width of read image
117+
lbp_image = np.zeros((image.shape[0], image.shape[1]))
118+
119+
# Iterating through the image and calculating the local binary pattern value
120+
# for each pixel.
121+
for i in range(0, image.shape[0]):
122+
for j in range(0, image.shape[1]):
123+
lbp_image[i][j] = lbp.local_binary_value(image, i, j)
124+
125+
assert lbp_image.any()

0 commit comments

Comments
 (0)