Use shared bilinear interpolation function and improve performance.

This commit is contained in:
Johannes Schönberger
2012-08-20 22:48:35 +02:00
parent 0ca7933a7d
commit 70b7745a34
3 changed files with 44 additions and 75 deletions
+13 -44
View File
@@ -1,10 +1,13 @@
#cython: cdivison=True
#cython: boundscheck=False
#cython: nonecheck=False
#cython: wraparound=False
import numpy as np
cimport numpy as np
cimport cython
from libc.math cimport sin, cos, abs, ceil, floor
from libc.math cimport sin, cos, abs
from skimage.transform._project cimport bilinear_interpolation
@cython.boundscheck(False)
def _glcm_loop(np.ndarray[dtype=np.uint8_t, ndim=2,
negative_indices=False, mode='c'] image,
np.ndarray[dtype=np.float64_t, ndim=1,
@@ -62,42 +65,7 @@ def _glcm_loop(np.ndarray[dtype=np.uint8_t, ndim=2,
out[i, j, d_idx, a_idx] += 1
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
@cython.cdivision(True)
cdef _bilinear_interpolation(np.ndarray[double, ndim=2] image,
np.ndarray[double, ndim=2] coords,
np.ndarray[double, ndim=1] output,
double r0=0, double c0=0, double cval=0):
cdef double r, c, dr, dc
cdef int i, minr, minc, maxr, maxc
for i in range(coords.shape[0]):
r = r0 + coords[i, 0]
c = c0 + coords[i, 1]
minr = <int>floor(r)
minc = <int>floor(c)
maxr = <int>ceil(r)
maxc = <int>ceil(c)
dr = r - minr
dc = c - minc
if (
minr < 0 or maxr >= image.shape[0]
or minc < 0 or maxc >= image.shape[1]
):
output[i] = cval
else:
top = (1 - dc) * image[minr, minc] + dc * image[minr, maxc]
bottom = (1 - dc) * image[maxr, minc] + dc * image[maxr, maxc]
output[i] = (1 - dr) * top + dr * bottom
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
@cython.cdivision(True)
cdef int _bit_rotate_right(int value, int length):
cdef inline int _bit_rotate_right(int value, int length):
"""Cyclic bit shift to the right.
Parameters
@@ -111,10 +79,6 @@ cdef int _bit_rotate_right(int value, int length):
return (value >> 1) | ((value & 1) << (length - 1))
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
@cython.cdivision(True)
def _local_binary_pattern(np.ndarray[double, ndim=2] image,
int P, float R, int method=0):
# texture weights
@@ -132,11 +96,16 @@ def _local_binary_pattern(np.ndarray[double, ndim=2] image,
output_shape = (image.shape[0], image.shape[1])
cdef np.ndarray[double, ndim=2] output = np.zeros(output_shape, 'double')
cdef int rows = image.shape[0]
cdef int cols = image.shape[1]
cdef double lbp
cdef int r, c, changes, i
for r in range(image.shape[0]):
for c in range(image.shape[1]):
_bilinear_interpolation(image, coords, texture, r, c)
for i in range(P):
texture[i] = bilinear_interpolation(<double*>image.data,
rows, cols, r + coords[i, 0], c + coords[i, 1], 'C')
# signed / thresholded texture
for i in range(P):
if texture[i] - image[r, c] >= 0:
+2 -1
View File
@@ -16,7 +16,8 @@ def configuration(parent_package='', top_path=None):
cython(['_template.pyx'], working_path=base_path)
config.add_extension('_texture', sources=['_texture.c'],
include_dirs=[get_numpy_include_dirs()])
include_dirs=[get_numpy_include_dirs(),
'../transform'])
config.add_extension('_template', sources=['_template.c'],
include_dirs=[get_numpy_include_dirs()])
+29 -30
View File
@@ -154,49 +154,48 @@ class TestLBP():
def test_default(self):
lbp = local_binary_pattern(self.image, 8, 1, 'default')
ref = np.array([[ 0., 241., 0., 255., 96., 255.],
[135., 0., 20., 153., 64., 56.],
[198., 255., 12., 191., 0., 124.],
[129., 64., 62., 159., 199., 0.],
[255., 4., 255., 175., 0., 124.],
[ 3., 5., 0., 255., 4., 24.]])
print lbp
ref = np.array([[ 0, 251, 0, 255, 96, 255],
[143, 0, 20, 153, 64, 56],
[238, 255, 12, 191, 0, 252],
[129, 64., 62, 159, 199, 0],
[255, 4, 255, 175, 0, 254],
[ 3, 5, 0, 255, 4, 24]])
np.testing.assert_array_equal(lbp, ref)
def test_ror(self):
lbp = local_binary_pattern(self.image, 8, 1, 'ror')
ref = np.array([[ 0., 31., 0., 255., 3., 255.],
[ 15., 0., 5., 51., 1., 7.],
[ 27., 255., 3., 127., 0., 31.],
[ 3., 1., 31., 63., 31., 0.],
[255., 1., 255., 95., 0., 31.],
[ 3., 5., 0., 255., 1., 3.]])
ref = np.array([[ 0, 127, 0, 255, 3, 255],
[ 31, 0, 5, 51, 1, 7],
[119, 255, 3, 127, 0, 63],
[ 3, 1, 31, 63, 31, 0],
[255, 1, 255, 95, 0, 127],
[ 3, 5, 0, 255, 1, 3]])
np.testing.assert_array_equal(lbp, ref)
def test_uniform(self):
lbp = local_binary_pattern(self.image, 8, 1, 'uniform')
ref = np.array([[0., 5., 0., 8., 2., 8.],
[4., 0., 9., 9., 1., 3.],
[9., 8., 2., 7., 0., 5.],
[2., 1., 5., 6., 5., 0.],
[8., 1., 8., 9., 0., 5.],
[2., 9., 0., 8., 1., 2.]])
ref = np.array([[0, 7, 0, 8, 2, 8],
[5, 0, 9, 9, 1, 3],
[9, 8, 2, 7, 0, 6],
[2, 1, 5, 6, 5, 0],
[8, 1, 8, 9, 0, 7],
[2, 9, 0, 8, 1, 2]])
np.testing.assert_array_equal(lbp, ref)
def test_var(self):
lbp = local_binary_pattern(self.image, 8, 1, 'var')
ref = np.array([[0. , 0.00039254, 0. , 0.00089309,
0.00030782, 0.00203232],
[0.00037561, 0. , 0.00263827, 0.00163246,
0.00027414, 0.00039593],
[0.00170876, 0.00130368, 0.00042095, 0.00171893,
0. , 0.00044912],
[0.00021898, 0.00019464, 0.00082291, 0.00225383,
ref = np.array([[0. , 0.00072786, 0. , 0.00115377,
0.00032355, 0.00224467],
[0.00051758, 0. , 0.0026383 , 0.00163246,
0.00027414, 0.00041124],
[0.00192834, 0.00130368, 0.00042095, 0.00171894,
0. , 0.00063726],
[0.00023048, 0.00019464 , 0.00082291, 0.00225386,
0.00076696, 0. ],
[0.00079791, 0.00013236, 0.0009134 , 0.0014467 ,
0. , 0.00046857],
[0.00022553, 0.00089319, 0. , 0.00089274,
0.00013659, 0.00031981]])
[0.00097253, 0.00013236, 0.0009134 , 0.0014467 ,
0. , 0.00082472],
[0.00024701, 0.0012277 , 0. , 0.00109869,
0.00015445, 0.00035881]])
np.testing.assert_array_almost_equal(lbp, ref)