MBLBP optimized by taking out constants definition out of function. Visualization function of MBLBP now supports colors and opacity. Examples are updated.

This commit is contained in:
dan
2015-06-09 14:18:58 +02:00
parent 83c3bd10c8
commit d39434c30e
4 changed files with 60 additions and 70 deletions
@@ -7,18 +7,18 @@ In this example, we will see how to compute the multi-block
local binary pattern at a specified image and how to visualize it.
The features are calculated in a way similar to local binary
patterns, except that block summed up pixel values
patterns, except that summed up pixel values
rather than pixel values are used.
`MB-LBP` is an extension of LBP that can be computed on any
scales in a constant time using integral image. It consists of
scale in a constant time using integral image. It consists of
`9` equal-sized rectangles. They are used to compute a feature.
Sum of pixels' intensity values in each of them are compared
to the central rectangle and depending on comparison result,
the feature descriptor is computed.
We will start with a simple image that we will generate by our
own to show how the `MB-LBP` works. We will create a `(9, 9)`
We will start with a simple image that we will generate
to show how the `MB-LBP` works. We will create a `(9, 9)`
rectangle with and divide it into `9` blocks. After this
we will apply `MB-LBP` on it.
@@ -55,10 +55,8 @@ print(lbp_code == correct_answer)
"""
Now let's apply the operator to a real image and see how the visualization works.
"""
from __future__ import print_function
from skimage.feature import (multiblock_local_binary_pattern,
visualize_multiblock_lbp)
draw_multiblock_lbp)
from skimage.util import img_as_float
from skimage.transform import integral_image
from skimage import data
@@ -71,8 +69,8 @@ int_img = integral_image(test_img)
lbp_code = multiblock_local_binary_pattern(int_img, 0, 0, 90, 90)
img = visualize_multiblock_lbp(test_img, 0, 0, 90, 90,
lbp_code=lbp_code)
img = draw_multiblock_lbp(test_img, 0, 0, 90, 90,
lbp_code=lbp_code, alpha=0.5)
plt.imshow(img, interpolation='nearest')
+2 -2
View File
@@ -3,7 +3,7 @@ from ._daisy import daisy
from ._hog import hog
from .texture import (greycomatrix, greycoprops,
local_binary_pattern,
visualize_multiblock_lbp)
draw_multiblock_lbp)
from ._texture import multiblock_local_binary_pattern
from .peak import peak_local_max
@@ -30,7 +30,7 @@ __all__ = ['canny',
'greycoprops',
'local_binary_pattern',
'multiblock_local_binary_pattern',
'visualize_multiblock_lbp',
'draw_multiblock_lbp',
'peak_local_max',
'structure_tensor',
'structure_tensor_eigvals',
+15 -45
View File
@@ -266,35 +266,9 @@ def _local_binary_pattern(double[:, ::1] image,
return np.asarray(output)
cdef inline Py_ssize_t _clip(Py_ssize_t x, Py_ssize_t low,
Py_ssize_t high) nogil:
"""Clips coordinate between high and low.
Parameters
----------
x : int
Coordinate to be clipped.
low : int
The lower bound.
high : int
The higher bound.
Returns
-------
x : int
`x` clipped between `high` and `low`.
"""
if(x > high):
return high
if(x < low):
return low
return x
cdef inline cnp.double_t _integ(
cnp.double_t[:, ::1] img, Py_ssize_t r0, Py_ssize_t c0,
Py_ssize_t r1, Py_ssize_t c1) nogil:
cdef inline cnp.double_t _integ(cnp.double_t[:, ::1] img,
Py_ssize_t r0, Py_ssize_t c0,
Py_ssize_t r1, Py_ssize_t c1) nogil:
"""Integrate over the integral image in the given window
This method was created so that `multiblock_local_binary_pattern`
@@ -319,12 +293,6 @@ cdef inline cnp.double_t _integ(
The integral over the given window.
"""
r = _clip(r0, 0, img.shape[0] - 1)
c = _clip(c0, 0, img.shape[1] - 1)
r2 = _clip(r1, 0, img.shape[0] - 1)
c2 = _clip(c1, 0, img.shape[1] - 1)
cdef cnp.double_t ans = img[r1, c1]
if (r0 >= 1) and (c0 >= 1):
@@ -339,6 +307,14 @@ cdef inline cnp.double_t _integ(
return ans
# Constant values that are used by `multiblock_local_binary_pattern` function.
# These values are taken out for performance improvement.
# Values represent offsets of neighbour rectangles relative to central one.
# It has order starting from top left and going clockwise.
cdef:
Py_ssize_t[::1] mlbp_x_offsets = np.asarray([-1, 0, 1, 1, 1, 0, -1, -1])
Py_ssize_t[::1] mlbp_y_offsets = np.asarray([-1, -1, -1, 0, 1, 1, 1, 0])
def multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
Py_ssize_t x,
Py_ssize_t y,
@@ -347,11 +323,11 @@ def multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
"""Multi-block local binary pattern.
The features are calculated in a way similar to local binary
patterns, except that block summed up pixel values
patterns, except that summed up pixel values
rather than pixel values are used.
MB-LBP is an extension of LBP that can be computed on any
scales in a constant time using integral image. It consists of
scale in a constant time using integral image. It consists of
9 equal-sized rectangles. They are used to compute a feature.
Sum of pixels' intensity values in each of them are compared
to the central rectangle and depending on comparison result,
@@ -397,13 +373,7 @@ def multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
central_rect_y + height - 1,
central_rect_x + width - 1)
#print central_rect_x, central_rect_y
# Offsets of neighbour rectangles relative to central one.
# It has order starting from top left and going clockwise
cdef:
Py_ssize_t *x_offsets = [-1, 0, 1, 1, 1, 0, -1, -1]
Py_ssize_t *y_offsets = [-1, -1, -1, 0, 1, 1, 1, 0]
Py_ssize_t element_num, offset_x, offset_y
Py_ssize_t current_rect_x, current_rect_y
double current_rect_val
@@ -412,8 +382,8 @@ def multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
for element_num in range(8):
offset_x = x_offsets[element_num]
offset_y = y_offsets[element_num]
offset_x = mlbp_x_offsets[element_num]
offset_y = mlbp_y_offsets[element_num]
current_rect_x = central_rect_x + offset_x * width
+36 -14
View File
@@ -294,7 +294,16 @@ def local_binary_pattern(image, P, R, method='default'):
return output
def visualize_multiblock_lbp(img, x, y, width, height, lbp_code=0):
def draw_multiblock_lbp(img,
x,
y,
width,
height,
lbp_code=0,
color_greater_block=[1, 1, 1],
color_less_block=[0, 0.69, 0.96],
alpha=0.5
):
"""Multi-block local binary pattern visualization.
MB-LBP is an extension of LBP that can be computed on many
@@ -326,11 +335,24 @@ def visualize_multiblock_lbp(img, x, y, width, height, lbp_code=0):
lbp_code : int
The descriptor of feature to visualize. If not provided,
the descriptor with 0 value will be used.
color_greater_block : list of 3 floats
Floats specifying the color for the block that
has greater intensity value. They should be
in the range [0, 1]. Corresponding values define
(R, G, B) values. Default value is white [1, 1, 1].
color_greater_block : list of 3 floats
Floats specifying the color for the block that
has greater intensity value. They should be
in the range [0, 1]. Corresponding values define
(R, G, B) values. Default value is cyan [0, 0.69, 0.96].
alpha : float
Value in the range [0, 1] that specifies opacity of
visualization. 1 - fully transparent, 0 - opaque.
Returns
-------
output :
Float image with visualization.
output : ndarray of float
Image with visualization.
References
----------
@@ -343,26 +365,26 @@ def visualize_multiblock_lbp(img, x, y, width, height, lbp_code=0):
# Default colors for regions.
# White is for the blocks that are brighter.
# Cyan is for the blocks that has less intensity.
color_greater_block = np.asarray([1, 1, 1], dtype='float64')
color_less_block = np.asarray([0, 0.69, 0.96], dtype='float64')
color_greater_block = np.asarray(color_greater_block, dtype='float64')
color_less_block = np.asarray(color_less_block, dtype='float64')
# Copy array to avoid the changes to the original one
# Copy array to avoid the changes to the original one.
output = np.copy(img)
# As the visualization uses RGB color we need 3 bands.
if len(img.shape) < 3:
output = np.dstack((img,) * 3)
# Colors are specified in floats
# Colors are specified in floats.
output = img_as_float(output)
# Offsets of neighbour rectangles relative to central one.
# It has order starting from top left and going clockwise
# It has order starting from top left and going clockwise.
neighbour_rect_offsets = ((-1, -1), (0, -1), (1, -1),
(1, 0), (1, 1), (0, 1),
(-1, 1), (-1, 0))
# Top-left coordinates of central rectangle
# Top-left coordinates of central rectangle.
central_rect_x = x + width
central_rect_y = y + height
@@ -375,14 +397,14 @@ def visualize_multiblock_lbp(img, x, y, width, height, lbp_code=0):
has_greater_value = lbp_code & (1 << (7-element_num))
# Mix-in the visualization colors
# Mix-in the visualization colors.
if has_greater_value:
output[curr_y:curr_y+height, curr_x:curr_x+width] = \
0.5 * output[curr_y:curr_y+height, curr_x:curr_x+width] \
+ 0.5 * color_greater_block
(1-alpha) * output[curr_y:curr_y+height, curr_x:curr_x+width] \
+ alpha * color_greater_block
else:
output[curr_y:curr_y+height, curr_x:curr_x+width] = \
0.5 * output[curr_y:curr_y+height, curr_x:curr_x+width] \
+ 0.5 * color_less_block
(1-alpha) * output[curr_y:curr_y+height, curr_x:curr_x+width] \
+ alpha * color_less_block
return output