From 824997af0a4c0070c5ddaade9c21efaaaac61e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Tue, 21 Aug 2012 08:32:20 +0200 Subject: [PATCH] Move bilinear interpolation code to shared package --- .../interpolation.pxd} | 8 +- skimage/_shared/interpolation.pyx | 104 ++++++++++++++++++ skimage/_shared/setup.py | 5 + skimage/feature/_texture.pyx | 2 +- skimage/setup.py | 1 + skimage/transform/_project.pyx | 102 +---------------- skimage/transform/setup.py | 2 +- 7 files changed, 118 insertions(+), 106 deletions(-) rename skimage/{transform/_project.pxd => _shared/interpolation.pxd} (52%) create mode 100644 skimage/_shared/interpolation.pyx diff --git a/skimage/transform/_project.pxd b/skimage/_shared/interpolation.pxd similarity index 52% rename from skimage/transform/_project.pxd rename to skimage/_shared/interpolation.pxd index dee51026..7ad5d223 100644 --- a/skimage/transform/_project.pxd +++ b/skimage/_shared/interpolation.pxd @@ -1,7 +1,9 @@ -cimport numpy as np -import numpy as np - cdef inline double bilinear_interpolation(double* image, int rows, int cols, double r, double c, char mode, double cval=*) + +cdef inline double get_pixel(double* image, int rows, int cols, int r, int c, + char mode, double cval=*) + +cdef inline int coord_map(int dim, int coord, char mode) diff --git a/skimage/_shared/interpolation.pyx b/skimage/_shared/interpolation.pyx new file mode 100644 index 00000000..defa2e9b --- /dev/null +++ b/skimage/_shared/interpolation.pyx @@ -0,0 +1,104 @@ +#cython: cdivison=True +#cython: boundscheck=False +#cython: nonecheck=False +#cython: wraparound=False +from libc.math cimport ceil, floor + + +cdef inline double bilinear_interpolation(double* image, int rows, int cols, + double r, double c, char mode, + double cval=0): + """Bilinear interpolation at a given position in the image. + + Parameters + ---------- + image : double array + Input image. + rows, cols: int + Shape of image. + r, c : int + Position at which to interpolate. + mode : {'C', 'W', 'M'} + Wrapping mode. Constant, Wrap or Mirror. + cval : double + Constant value to use for constant mode. + + """ + cdef double dr, dc + cdef int minr, minc, maxr, maxc + + minr = floor(r) + minc = floor(c) + maxr = ceil(r) + maxc = ceil(c) + dr = r - minr + dc = c - minc + top = (1 - dc) * get_pixel(image, rows, cols, minr, minc, mode, cval) \ + + dc * get_pixel(image, rows, cols, minr, maxc, mode, cval) + bottom = (1 - dc) * get_pixel(image, rows, cols, maxr, minc, mode, cval) \ + + dc * get_pixel(image, rows, cols, maxr, maxc, mode, cval) + return (1 - dr) * top + dr * bottom + + +cdef inline double get_pixel(double* image, int rows, int cols, int r, int c, + char mode, double cval=0): + """Get a pixel from the image, taking wrapping mode into consideration. + + Parameters + ---------- + image : double array + Input image. + rows, cols: int + Shape of image. + r, c : int + Position at which to get the pixel. + mode : {'C', 'W', 'M'} + Wrapping mode. Constant, Wrap or Mirror. + cval : double + Constant value to use for constant mode. + + """ + if mode == 'C': + if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1): + return cval + else: + return image[r * cols + c] + else: + return image[coord_map(rows, r, mode) * cols + coord_map(cols, c, mode)] + + +cdef inline int coord_map(int dim, int coord, char mode): + """ + Wrap a coordinate, according to a given mode. + + Parameters + ---------- + dim : int + Maximum coordinate. + coord : int + Coord provided by user. May be < 0 or > dim. + mode : {'W', 'M'} + Whether to wrap or mirror the coordinate if it + falls outside [0, dim). + + """ + dim = dim - 1 + if mode == 'M': # mirror + if (coord < 0): + # How many times times does the coordinate wrap? + if ((-coord / dim) % 2 != 0): + return dim - (-coord % dim) + else: + return (-coord % dim) + elif (coord > dim): + if ((coord / dim) % 2 != 0): + return (dim - (coord % dim)) + else: + return (coord % dim) + elif mode == 'W': # wrap + if (coord < 0): + return (dim - (-coord % dim)) + elif (coord > dim): + return (coord % dim) + + return coord diff --git a/skimage/_shared/setup.py b/skimage/_shared/setup.py index 913a020c..6e4d1b6b 100644 --- a/skimage/_shared/setup.py +++ b/skimage/_shared/setup.py @@ -13,6 +13,11 @@ def configuration(parent_package='', top_path=None): config = Configuration('_shared', parent_package, top_path) config.add_data_dir('tests') + cython(['interpolation.pyx'], working_path=base_path) + + config.add_extension('interpolation', sources=['interpolation.c'], + include_dirs=[get_numpy_include_dirs()]) + return config diff --git a/skimage/feature/_texture.pyx b/skimage/feature/_texture.pyx index ca51e177..20b61513 100644 --- a/skimage/feature/_texture.pyx +++ b/skimage/feature/_texture.pyx @@ -5,7 +5,7 @@ import numpy as np cimport numpy as np from libc.math cimport sin, cos, abs -from skimage.transform._project cimport bilinear_interpolation +from skimage._shared.interpolation cimport bilinear_interpolation def _glcm_loop(np.ndarray[dtype=np.uint8_t, ndim=2, diff --git a/skimage/setup.py b/skimage/setup.py index 02c0b52d..1082ba07 100644 --- a/skimage/setup.py +++ b/skimage/setup.py @@ -6,6 +6,7 @@ def configuration(parent_package='', top_path=None): config = Configuration('skimage', parent_package, top_path) + config.add_subpackage('_shared') config.add_subpackage('color') config.add_subpackage('data') config.add_subpackage('draw') diff --git a/skimage/transform/_project.pyx b/skimage/transform/_project.pyx index 3f31f229..300ba543 100644 --- a/skimage/transform/_project.pyx +++ b/skimage/transform/_project.pyx @@ -5,107 +5,7 @@ cimport numpy as np import numpy as np -from cython.operator import dereference -from libc.math cimport ceil, floor - - -cdef inline double bilinear_interpolation(double* image, int rows, int cols, - double r, double c, char mode, - double cval=0): - """Bilinear interpolation at a given position in the image. - - Parameters - ---------- - image : double array - Input image. - rows, cols: int - Shape of image. - r, c : int - Position at which to interpolate. - mode : {'C', 'W', 'M'} - Wrapping mode. Constant, Wrap or Mirror. - cval : double - Constant value to use for constant mode. - - """ - cdef double dr, dc - cdef int minr, minc, maxr, maxc - - minr = floor(r) - minc = floor(c) - maxr = ceil(r) - maxc = ceil(c) - dr = r - minr - dc = c - minc - top = (1 - dc) * get_pixel(image, rows, cols, minr, minc, mode, cval) \ - + dc * get_pixel(image, rows, cols, minr, maxc, mode, cval) - bottom = (1 - dc) * get_pixel(image, rows, cols, maxr, minc, mode, cval) \ - + dc * get_pixel(image, rows, cols, maxr, maxc, mode, cval) - return (1 - dr) * top + dr * bottom - - -cdef inline double get_pixel(double* image, int rows, int cols, int r, int c, - char mode, double cval=0): - """Get a pixel from the image, taking wrapping mode into consideration. - - Parameters - ---------- - image : double array - Input image. - rows, cols: int - Shape of image. - r, c : int - Position at which to get the pixel. - mode : {'C', 'W', 'M'} - Wrapping mode. Constant, Wrap or Mirror. - cval : double - Constant value to use for constant mode. - - """ - if mode == 'C': - if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1): - return cval - else: - return image[r * cols + c] - else: - return image[coord_map(rows, r, mode) * cols + coord_map(cols, c, mode)] - - -cdef inline int coord_map(int dim, int coord, char mode): - """ - Wrap a coordinate, according to a given mode. - - Parameters - ---------- - dim : int - Maximum coordinate. - coord : int - Coord provided by user. May be < 0 or > dim. - mode : {'W', 'M'} - Whether to wrap or mirror the coordinate if it - falls outside [0, dim). - - """ - dim = dim - 1 - if mode == 'M': # mirror - if (coord < 0): - # How many times times does the coordinate wrap? - if ((-coord / dim) % 2 != 0): - return dim - (-coord % dim) - else: - return (-coord % dim) - elif (coord > dim): - if ((coord / dim) % 2 != 0): - return (dim - (coord % dim)) - else: - return (coord % dim) - elif mode == 'W': # wrap - if (coord < 0): - return (dim - (-coord % dim)) - elif (coord > dim): - return (coord % dim) - - return coord +from skimage._shared.interpolation cimport bilinear_interpolation cdef inline _matrix_transform(double x, double y, double* H, double *x_, diff --git a/skimage/transform/setup.py b/skimage/transform/setup.py index 4ecb6ba4..75210b54 100644 --- a/skimage/transform/setup.py +++ b/skimage/transform/setup.py @@ -20,7 +20,7 @@ def configuration(parent_package='', top_path=None): include_dirs=[get_numpy_include_dirs()]) config.add_extension('_project', sources=['_project.c'], - include_dirs=[get_numpy_include_dirs()]) + include_dirs=[get_numpy_include_dirs(), '../_shared']) return config