mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-04 13:23:29 +08:00
Switched to using integrate Cython function from skimage._shared. All changes were made to make it fit.
This commit is contained in:
@@ -3,36 +3,33 @@
|
||||
Multi-Block Local Binary Pattern for texture classification
|
||||
===========================================================
|
||||
|
||||
In this example, we will see how to compute the multi-block
|
||||
local binary pattern at a specified image and how to visualize it.
|
||||
This example shows how to compute multi-block local binary
|
||||
pattern (MB-LBP) features as well as how to visualize them.
|
||||
|
||||
The features are calculated in a way similar to local binary
|
||||
patterns, except that summed up pixel values
|
||||
rather than pixel values are used.
|
||||
The features are calculated similarly to local binary patterns (LBPs),
|
||||
except that summed blocks are used instead of individual pixel values.
|
||||
|
||||
`MB-LBP` is an extension of LBP that can be computed on any
|
||||
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.
|
||||
MB-LBP is an extension of LBP that can be computed on multiple scales
|
||||
in constant time using the integral image.
|
||||
9 equally-sized rectangles are used to compute a feature.
|
||||
For each rectangle, the sum of the pixel intensities is computed.
|
||||
Comparisons of these sums to that of the central rectangle determine
|
||||
the feature, similarly to LBP (See `LBP <plot_local_binary_pattern.html>`_).
|
||||
|
||||
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.
|
||||
First, we generate an image to illustrate the functioning of MB-LBP:
|
||||
we take a (9, 9) rectangle and divide it into (3, 3) block,
|
||||
upon which we then apply MB-LBP.
|
||||
|
||||
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from skimage.feature import multiblock_local_binary_pattern
|
||||
import numpy as np
|
||||
from skimage.util import img_as_float
|
||||
from skimage.transform import integral_image
|
||||
|
||||
# Create dummy matrix where first and fifth
|
||||
# rectangles have greater value than the central one
|
||||
# Therefore, the following bits should be 1.
|
||||
# Create test matrix where first and fifth
|
||||
# rectangles starting from top left clockwise
|
||||
# have greater value than the central one.
|
||||
test_img = np.zeros((9, 9), dtype='uint8')
|
||||
test_img[3:6, 3:6] = 1
|
||||
test_img[:3, :3] = 50
|
||||
@@ -43,14 +40,12 @@ test_img[6:, 6:] = 50
|
||||
# be filled.
|
||||
correct_answer = 0b10001000
|
||||
|
||||
# The function accepts the float images.
|
||||
# Also it has to be C-contiguous.
|
||||
test_img = img_as_float(test_img)
|
||||
int_img = integral_image(test_img)
|
||||
|
||||
lbp_code = multiblock_local_binary_pattern(int_img, 0, 0, 3, 3)
|
||||
|
||||
print(lbp_code == correct_answer)
|
||||
print(correct_answer)
|
||||
print(lbp_code)
|
||||
|
||||
"""
|
||||
Now let's apply the operator to a real image and see how the visualization works.
|
||||
@@ -61,7 +56,6 @@ from skimage.feature import draw_multiblock_lbp
|
||||
|
||||
test_img = data.coins()
|
||||
|
||||
test_img = img_as_float(test_img)
|
||||
int_img = integral_image(test_img)
|
||||
|
||||
lbp_code = multiblock_local_binary_pattern(int_img, 0, 0, 90, 90)
|
||||
@@ -75,8 +69,8 @@ plt.imshow(img, interpolation='nearest')
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
On the above plot we see the result of computing a `MB-LBP` and visualization
|
||||
On the above plot we see the result of computing a MB-LBP and visualization
|
||||
of the computed feature. The rectangles that have less intensity than the central
|
||||
rectangle are marked with cyan color. The ones that have bigger intensity values
|
||||
are marked with white color. The central rectangle is left untouched.
|
||||
rectangle are marked in cyan. The ones that have bigger intensity values
|
||||
are marked in white. The central rectangle is left untouched.
|
||||
"""
|
||||
|
||||
@@ -6,6 +6,7 @@ import numpy as np
|
||||
cimport numpy as cnp
|
||||
from libc.math cimport sin, cos, abs
|
||||
from .._shared.interpolation cimport bilinear_interpolation, round
|
||||
from .._shared.transform cimport integrate
|
||||
|
||||
|
||||
cdef extern from "numpy/npy_math.h":
|
||||
@@ -266,47 +267,6 @@ def _local_binary_pattern(double[:, ::1] image,
|
||||
return np.asarray(output)
|
||||
|
||||
|
||||
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`
|
||||
does not have to make a Python call.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
img : array
|
||||
The integral image over which to integrate.
|
||||
r0 : int
|
||||
The row number of the top left corner.
|
||||
c0 : int
|
||||
The column number of the top left corner.
|
||||
r1 : int
|
||||
The row number of the bottom right corner.
|
||||
c1 : int
|
||||
The column number of the bottom right corner.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ans : double
|
||||
The integral over the given window.
|
||||
"""
|
||||
|
||||
cdef cnp.double_t ans = img[r1, c1]
|
||||
|
||||
if (r0 >= 1) and (c0 >= 1):
|
||||
ans += img[r0 - 1, c0 - 1]
|
||||
|
||||
if (r0 >= 1):
|
||||
ans -= img[r0 - 1, c1]
|
||||
|
||||
if (c0 >= 1):
|
||||
ans -= img[r1, c0 - 1]
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
# Constant values that are used by `multiblock_local_binary_pattern` function.
|
||||
# Values represent offsets of neighbour rectangles relative to central one.
|
||||
# It has order starting from top left and going clockwise.
|
||||
@@ -314,18 +274,16 @@ 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])
|
||||
|
||||
cdef _multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
|
||||
Py_ssize_t x,
|
||||
Py_ssize_t y,
|
||||
Py_ssize_t width,
|
||||
Py_ssize_t height):
|
||||
cdef int _multiblock_local_binary_pattern(float[:, ::1] int_image,
|
||||
Py_ssize_t x,
|
||||
Py_ssize_t y,
|
||||
Py_ssize_t width,
|
||||
Py_ssize_t height):
|
||||
"""Multi-block local binary pattern.
|
||||
|
||||
Effcient implementation in Cython.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
int_image : (N, M) double array
|
||||
int_image : (N, M) float array
|
||||
Integral image.
|
||||
x : int
|
||||
X-coordinate of top left corner of a rectangle containing feature.
|
||||
@@ -341,7 +299,7 @@ cdef _multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
|
||||
Returns
|
||||
-------
|
||||
output : int
|
||||
8bit MB-LBP feature descriptor.
|
||||
8-bit MB-LBP feature descriptor.
|
||||
|
||||
References
|
||||
----------
|
||||
@@ -357,11 +315,11 @@ cdef _multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
|
||||
Py_ssize_t central_rect_y = y + height
|
||||
|
||||
# Sum of intensity values of central rectangle
|
||||
cdef double central_rect_val = _integ(int_image,
|
||||
central_rect_y,
|
||||
central_rect_x,
|
||||
central_rect_y + height - 1,
|
||||
central_rect_x + width - 1)
|
||||
cdef float central_rect_val = integrate(int_image,
|
||||
central_rect_y,
|
||||
central_rect_x,
|
||||
central_rect_y + height - 1,
|
||||
central_rect_x + width - 1)
|
||||
|
||||
cdef:
|
||||
Py_ssize_t element_num, offset_x, offset_y
|
||||
@@ -380,11 +338,11 @@ cdef _multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
|
||||
current_rect_y = central_rect_y + offset_y * height
|
||||
|
||||
|
||||
current_rect_val = _integ(int_image,
|
||||
current_rect_y,
|
||||
current_rect_x,
|
||||
current_rect_y + height - 1,
|
||||
current_rect_x + width - 1)
|
||||
current_rect_val = integrate(int_image,
|
||||
current_rect_y,
|
||||
current_rect_x,
|
||||
current_rect_y + height - 1,
|
||||
current_rect_x + width - 1)
|
||||
|
||||
|
||||
has_greater_value = current_rect_val >= central_rect_val
|
||||
@@ -396,23 +354,18 @@ cdef _multiblock_local_binary_pattern(cnp.double_t[:, ::1] int_image,
|
||||
return lbp_code
|
||||
|
||||
|
||||
def multiblock_local_binary_pattern(int_image,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height):
|
||||
def multiblock_local_binary_pattern(int_image, x, y, width, height):
|
||||
"""Multi-block local binary pattern.
|
||||
|
||||
The features are calculated in a way similar to local binary
|
||||
patterns, except that summed up pixel values
|
||||
rather than pixel values are used.
|
||||
The features are calculated similarly to local binary patterns (LBPs),
|
||||
except that summed blocks are used instead of individual pixel values.
|
||||
|
||||
MB-LBP is an extension of LBP that can be computed on any
|
||||
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.
|
||||
MB-LBP is an extension of LBP that can be computed on multiple scales
|
||||
in constant time using the integral image.
|
||||
9 equally-sized rectangles are used to compute a feature.
|
||||
For each rectangle, the sum of the pixel intensities is computed.
|
||||
Comparisons of these sums to that of the central rectangle determine
|
||||
the feature, similarly to LBP.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -442,7 +395,7 @@ def multiblock_local_binary_pattern(int_image,
|
||||
http://www.cbsr.ia.ac.cn/users/scliao/papers/Zhang-ICB07-MBLBP.pdf
|
||||
"""
|
||||
|
||||
int_image = np.ascontiguousarray(int_image, dtype=np.double)
|
||||
int_image = np.ascontiguousarray(int_image, dtype=np.float32)
|
||||
lbp_code = _multiblock_local_binary_pattern(int_image, x, y, width, height)
|
||||
return lbp_code
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ from skimage.feature import (
|
||||
|
||||
from skimage._shared.testing import test_parallel
|
||||
from skimage.transform import integral_image
|
||||
from skimage.util import img_as_float
|
||||
|
||||
class TestGLCM():
|
||||
|
||||
@@ -253,9 +252,6 @@ class TestMBLBP():
|
||||
# be filled.
|
||||
correct_answer = 0b10001000
|
||||
|
||||
# The function accepts the float images.
|
||||
# Also it has to be C-contiguous.
|
||||
test_img = img_as_float(test_img)
|
||||
int_img = integral_image(test_img)
|
||||
|
||||
lbp_code = multiblock_local_binary_pattern(int_img, 0, 0, 3, 3)
|
||||
|
||||
@@ -306,11 +306,11 @@ def draw_multiblock_lbp(img,
|
||||
):
|
||||
"""Multi-block local binary pattern visualization.
|
||||
|
||||
The blocks visualized in the following manner: the center block
|
||||
is left untouched. The blocks that have higher are covered with
|
||||
transparent white rectangles. The blocks that have less intensity
|
||||
are covered with cyan rectangles. The colors can also be specified.
|
||||
Opacity of visualization is controlled with `alpha` argument.
|
||||
Blocks with higher sums are colored with transparent white rectangles,
|
||||
whereas blocks with lower sums are colored cyan.
|
||||
The blocks that have less intensity are covered with
|
||||
cyan rectangles. The colors can also be specified.
|
||||
Opacity of visualization is controlled with `alpha` parameter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -359,8 +359,8 @@ def draw_multiblock_lbp(img,
|
||||
# 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(color_greater_block, dtype='float64')
|
||||
color_less_block = np.asarray(color_less_block, dtype='float64')
|
||||
color_greater_block = np.asarray(color_greater_block, dtype=np.double)
|
||||
color_less_block = np.asarray(color_less_block, dtype=np.double)
|
||||
|
||||
# Copy array to avoid the changes to the original one.
|
||||
output = np.copy(img)
|
||||
|
||||
Reference in New Issue
Block a user