Switched to using integrate Cython function from skimage._shared. All changes were made to make it fit.

This commit is contained in:
dan
2015-06-10 11:38:20 +02:00
parent c4f8e0126b
commit 61442e040e
4 changed files with 56 additions and 113 deletions
@@ -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.
"""
+28 -75
View File
@@ -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
-4
View File
@@ -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)
+7 -7
View File
@@ -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)