diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 3365b0df..43c559b8 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -70,3 +70,6 @@ - Brian Holt Histograms of Oriented Gradients + +- David-Warde Farley, Sturla Molden + Bresenheim line drawing, from snippets on numpy-discussion. diff --git a/TASKS.txt b/TASKS.txt index 8c99a40a..1d32b373 100644 --- a/TASKS.txt +++ b/TASKS.txt @@ -122,3 +122,7 @@ Implement Algorithms - Graph cut segmentation - Probabilistic Hough transform +Drawing +``````` +- Wu's algorithm for lines and circles + diff --git a/scikits/image/draw/__init__.py b/scikits/image/draw/__init__.py new file mode 100644 index 00000000..907a1ba7 --- /dev/null +++ b/scikits/image/draw/__init__.py @@ -0,0 +1 @@ +from draw import * diff --git a/scikits/image/draw/_draw.pyx b/scikits/image/draw/_draw.pyx new file mode 100644 index 00000000..a586ae03 --- /dev/null +++ b/scikits/image/draw/_draw.pyx @@ -0,0 +1,66 @@ +import numpy as np +cimport numpy as np +cimport cython + +cdef extern from "math.h": + int abs(int i) + +@cython.boundscheck(False) +@cython.wraparound(False) +def bresenham(int y, int x, int y2, int x2): + """ + Generate line pixel coordinates. + + Parameters + ---------- + y, x : int + Starting position (row, column). + y2, x2 : int + End position (row, column). + + Returns + ------- + rr, cc : (N,) ndarray of int + Indices of pixels that belong to the line. + May be used to directly index into an array, e.g. + ``img[rr, cc] = 1``. + + """ + cdef np.ndarray[np.int32_t, ndim=1, mode="c"] rr, cc + + cdef int steep = 0 + cdef int dx = abs(x2 - x) + cdef int dy = abs(y2 - y) + cdef int sx, sy, d, i + + if (x2 - x) > 0: sx = 1 + else: sx = -1 + if (y2 - y) > 0: sy = 1 + else: sy = -1 + if dy > dx: + steep = 1 + x,y = y,x + dx,dy = dy,dx + sx,sy = sy,sx + d = (2 * dy) - dx + + rr = np.zeros(int(dx) + 1, dtype=np.int32) + cc = np.zeros(int(dx) + 1, dtype=np.int32) + + for i in range(dx): + if steep: + rr[i] = x + cc[i] = y + else: + rr[i] = y + cc[i] = x + while d >= 0: + y = y + sy + d = d - (2 * dx) + x = x + sx + d = d + (2 * dy) + + rr[dx] = y2 + cc[dx] = x2 + + return rr, cc diff --git a/scikits/image/draw/draw.py b/scikits/image/draw/draw.py new file mode 100644 index 00000000..9360623a --- /dev/null +++ b/scikits/image/draw/draw.py @@ -0,0 +1,6 @@ +""" +Methods to draw on arrays. + +""" + +from _draw import bresenham diff --git a/scikits/image/draw/setup.py b/scikits/image/draw/setup.py new file mode 100644 index 00000000..3e0cd1a4 --- /dev/null +++ b/scikits/image/draw/setup.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +import os +from scikits.image._build import cython + +base_path = os.path.abspath(os.path.dirname(__file__)) + +def configuration(parent_package='', top_path=None): + from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs + + config = Configuration('draw', parent_package, top_path) + config.add_data_dir('tests') + + cython(['_draw.pyx'], working_path=base_path) + + config.add_extension('_draw', sources=['_draw.c'], + include_dirs=[get_numpy_include_dirs()]) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(maintainer = 'Scikits-image developers', + author = 'Scikits-image developers', + maintainer_email = 'scikits-image@googlegroups.com', + description = 'Drawing', + url = 'https://github.com/scikits-image/scikits.image', + license = 'SciPy License (BSD Style)', + **(configuration(top_path='').todict()) + ) diff --git a/scikits/image/draw/tests/test_draw.py b/scikits/image/draw/tests/test_draw.py new file mode 100644 index 00000000..06ebaac0 --- /dev/null +++ b/scikits/image/draw/tests/test_draw.py @@ -0,0 +1,52 @@ +from numpy.testing import assert_array_equal +import numpy as np + +from scikits.image.draw import bresenham + +def test_bresenham_horizontal(): + img = np.zeros((10, 10)) + + rr, cc = bresenham(0, 0, 0, 9) + img[rr, cc] = 1 + + img_ = np.zeros((10, 10)) + img_[0, :] = 1 + + assert_array_equal(img, img_) + +def test_bresenham_vertical(): + img = np.zeros((10, 10)) + + rr, cc = bresenham(0, 0, 9, 0) + img[rr, cc] = 1 + + img_ = np.zeros((10, 10)) + img_[:, 0] = 1 + + assert_array_equal(img, img_) + +def test_reverse(): + img = np.zeros((10, 10)) + + rr, cc = bresenham(0, 9, 0, 0) + img[rr, cc] = 1 + + img_ = np.zeros((10, 10)) + img_[0, :] = 1 + + assert_array_equal(img, img_) + +def test_diag(): + img = np.zeros((5, 5)) + + rr, cc = bresenham(0, 0, 4, 4) + img[rr, cc] = 1 + + img_ = np.eye(5) + + assert_array_equal(img, img_) + + +if __name__ == "__main__": + from numpy.testing import run_module_suite +