Mercurial > hg > octave-image
changeset 218:69bb85145ef5
First revision of bwarea.m and __bwarea.cc
author | hauberg |
---|---|
date | Thu, 28 Dec 2006 22:42:12 +0000 |
parents | 93ec20b95b4a |
children | 86749dc087db |
files | inst/bwdist.m src/Makefile src/__bwdist.cc |
diffstat | 3 files changed, 199 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/inst/bwdist.m @@ -0,0 +1,50 @@ +## Copyright (C) 2006 Søren Hauberg +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2, or (at your option) +## any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this file. If not, write to the Free Software Foundation, +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +## -*- texinfo -*- +## @deftypefn {Function File} @var{d} = bwdist(@var{bw}, @var{method}) +## Computes the distance transform of the binary image @var{bw}. +## The result @var{d} is a matrix of the same size as @var{bw}, where +## each value is the shortest distance to a non-zero pixel in @var{bw}. +## +## @var{method} changes the used distance function. Currently +## the Euclidian distance is the only supported distance function. +## @end deftypefn + +function D = bwdist(bw, method = "euclidian") + ## Check input + if (nargin == 0) + print_usage(); + endif + + if (!ismatrix(bw) || ndims(bw) != 2) + error("bwdist: input must be a 2-dimensional matrix"); + endif + + if (!ischar(method)) + error("bwdist: method name must be a string"); + endif + + ## Do the work + bw = (bw != 0); + switch (lower(method(1))) + case "e" + ## Euclidian distance transform + D = __bwdist(bw); + otherwise + error("bwdist: unsupported method '%s'", method); + endswitch +endfunction
--- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ endif all: cordflt2.oct bwlabel.oct bwfill.oct rotate_scale.oct \ - houghtf.oct graycomatrix.oct deriche.oct \ + houghtf.oct graycomatrix.oct deriche.oct __bwdist.oct \ $(JPEG) $(PNG) $(IMAGEMAGICK) jpgread.oct: jpgread.cc
new file mode 100644 --- /dev/null +++ b/src/__bwdist.cc @@ -0,0 +1,148 @@ +/* +Copyright (C) 2006 Pedro Felzenszwalb + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Remark by Søren Hauberg, december 28th 2006. + * + * This code was mainly written by Pedro Felzenszwalb and published + * on http://people.cs.uchicago.edu/~pff/dt/ + * Pedro kindly released his code under the GPL and I ported it to + * Octave. + */ + +#include <octave/oct.h> + +#define INF 1E20 + +template <class T> +inline T square(const T &x) { return x*x; }; + +/* dt of 1d function using squared distance */ +static float *dt(float *f, int n) { + float *d = new float[n]; + int *v = new int[n]; + float *z = new float[n+1]; + int k = 0; + v[0] = 0; + z[0] = -INF; + z[1] = +INF; + for (int q = 1; q <= n-1; q++) { + float s = ((f[q]+square(q))-(f[v[k]]+square(v[k])))/(2*q-2*v[k]); + while (s <= z[k]) { + k--; + s = ((f[q]+square(q))-(f[v[k]]+square(v[k])))/(2*q-2*v[k]); + } + k++; + v[k] = q; + z[k] = s; + z[k+1] = +INF; + } + + k = 0; + for (int q = 0; q <= n-1; q++) { + while (z[k+1] < q) + k++; + d[q] = square(q-v[k]) + f[v[k]]; + } + + delete [] v; + delete [] z; + return d; +} + +/* dt of 2d function using squared distance */ +static void dt(NDArray &im) { + const int width = im.dim2(); + const int height = im.dim1(); + float *f = new float[std::max(width,height)]; + + // transform along columns + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + f[y] = im(x, y); + } + float *d = dt(f, height); + for (int y = 0; y < height; y++) { + im(x, y) = d[y]; + } + delete [] d; + } + + // transform along rows + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + f[x] = im(x, y); + } + float *d = dt(f, width); + for (int x = 0; x < width; x++) { + im(x, y) = d[x]; + } + delete [] d; + } + + delete f; +} + + +/* dt of binary image using squared distance */ +void dt(boolNDArray &im, NDArray &out) { + const int width = im.dim2(); + const int height = im.dim1(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (im(x, y)) + out(x, y) = 0; + else + out(x, y) = INF; + } + } + + dt(out); +} + +DEFUN_DLD(__bwdist, args, nargout, "\ +-*- texinfo -*-\n\ +@deftypefn {Function File} __bwdist (@var{bw})\n\ +Computes the Euclidian Distance Transform for a binary image @var{bw}.\n\ +You should not call this function directly, instead call 'bwdist'.\n\ +@seealso{bwdist}\n\ +@end deftypefn\n\ +") +{ + octave_value_list retval; + + boolNDArray bw = args(0).bool_array_value(); + if (error_state) { + error("__bwdist: input must be a boolean matrix"); + return retval; + } + + const dim_vector dims = bw.dims(); + if (dims.length() != 2) { + error("__bwdist: currently only binary images are supported"); + return retval; + } + + NDArray *out = new NDArray(dims); + + dt(bw, *out); + + retval.append(*out); + return retval; +}