Mercurial > hg > octave-image
changeset 858:af3c7946534b
Follow coding guidelines and fix tests.
* imgradient.m, imgradientxy.m: turn the %! comments into test blocks, style
changes to follow coding guidelines (more whitespace, use of double quotes,
error messages, leave a single sentence at start of help text), set default
method in function prototype, replace windows CRLF with Unix LF.
* imgradient.m: compute second output argument if (nargout > 1) instead of
(nargout == 2), simplify the two possible usage to reduce code,
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Sun, 05 Jan 2014 08:27:27 +0000 |
parents | 75d6748324de |
children | 9e4ecfd52273 |
files | inst/imgradient.m inst/imgradientxy.m |
diffstat | 2 files changed, 225 insertions(+), 234 deletions(-) [+] |
line wrap: on
line diff
--- a/inst/imgradient.m +++ b/inst/imgradient.m @@ -1,115 +1,92 @@ -## Copyright (C) 2013 Brandon Miles <brandon.miles7 at gmail.com> -## -## 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 3 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, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{image}, @var{method}) -## @deftypefn {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{gx}, @var{gy}) -## Compute the gradient magnitude and direction in degrees for an image. These are computed from the -## x and y gradients using imgradientxy. The first input @var{image} is a gray -## scale image to compute the edges on. The second input @var{method} controls the method used to calculate -## the gradients. Alternatively the first input @var{gx} can be the x gradient and the second input @var{gy} can be the y gradient. -## The first output @var{gradMag} returns the magnitude of the gradient. The second output -## @var{gradDir} returns the direction in degrees. -## -## The @var{method} input argument can be any of the following strings (the default -## value is "Sobel") -## -## @table @asis -## @item "Sobel" -## Calculates the gradient in @var{image} using the Sobel approximation to the -## derivatives. -## -## @item "Prewitt" -## Calculates the gradient in @var{image} using the Prewitt approximation to the -## derivatives. This method works just like "Sobel" except a different approximation of -## the gradient is used. -## -## @item "Central Difference" -## Calculates the gradient in @var{image} using the central difference approximation to the -## derivatives: (x(i-1) - x(i+1))/2. -## -## @item "Intermediate Difference" -## Calculates the gradient in @var{image} using the intermediate difference approximation to -## the derivatives: x(i) - x(i+1). -## -## @end table -## -## @seealso{edge, gradientxy} -## @end deftypefn - -function [gradMag, gradDir] = imgradient (var1, var2) - - ## Get the image - if (nargin == 0) - error("imgradient: not enough input arguments"); - endif - if ( ndims(var1) > 2 ) - error("imgradient: first input must be a gray-scale image"); - endif - - ## Get the method - if (nargin == 1) - method = "Sobel"; - image = var1; - [gradX, gradY] = imgradientxy(image, method); - endif - - ## determine whether the two inputs are the same size - if(nargin == 2) - ## test for var2 as a string - if( ischar(var2)) - image = var1; - method = var2; - [gradX, gradY] = imgradientxy(image, method); - - ## use gx, gy instead - else - if( size(var2) != size(var1)) - error("imgradient: expected inputs gx, gy to be the same size") - endif - gradX = var1; - gradY = var2; - endif - endif - - gradMag = sqrt(gradX.^2 + gradY.^2); - - ## use atan2(-gy,gx)*pi/180 - ## see: http://stackoverflow.com/questions/18549015/why-imgradient-invert-vertical-when-computing-the-angle - if (nargout == 2) - gradDir = atan2d(-gradY,gradX); - end - -endfunction - -%% run tests -%!A = [0 1 0; 1 1 1; 0 1 0]; -%![gMag,gDir] = imgradient(A); -%!assert(gMag,[sqrt(18),4,sqrt(18); 4 0 4; sqrt(18),4,sqrt(18)]); -%!assert(gDir,[-45 -90 -135; -0 -0 -180; 45 90 135]); -%% -%% Test combinations -%![gxSobel, gySobel] = imgradientxy(A); -%![gxSobel2, gySobel2] = imgradientxy(A,'Sobel'); -%![gxPrewitt,gyPrewitt] = imgradientxy(A,'Prewitt'); -%![gxCd,gyCd] = imgradientxy(A,'CentralDifference'); -%![gxId,gyId] = imgradientxy(A,'IntermediateDifference'); -%% -%!assert(imgradient(A),imgradient(gxSobel,gySobel)); -%!assert(imgradient(A,'Sobel'),imgradient(gxSobel2,gySobel2)); -%!assert(imgradient(A,'Prewitt'),imgradient(gxPrewitt,gyPrewitt)); -%!assert(imgradient(A,'CentralDifference'),imgradient(gxCd,gyCd)); -%!assert(imgradient(A,'IntermediateDifference'),imgradient(gxId,gyId)); - \ No newline at end of file +## Copyright (C) 2013 Brandon Miles <brandon.miles7@gmail.com> +## +## 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 3 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, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{img}) +## @deftypefn {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{img}, @var{method}) +## @deftypefnx {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{gx}, @var{gy}) +## Compute the gradient magnitude and direction in degrees for an image. +## +## These are computed from the @var{gx} and @var{xy} gradients using +## @code{imgradientxy}. The first input @var{img} is a gray scale image to +## compute the edges on. The second input @var{method} controls the method +## used to calculate the gradients. Alternatively the first input @var{gx} +## can be the x gradient and the second input @var{gy} can be the y gradient. +## +## The first output @var{gradMag} returns the magnitude of the gradient. +## The second output @var{gradDir} returns the direction in degrees. +## +## The @var{method} input argument must be a string specifying one of the +## methods supported by @code{imgradientxy}. +## +## @seealso{edge, imgradientxy} +## @end deftypefn + +function [gradMag, gradDir] = imgradient (img, method = "sobel") + + if (nargin < 1 || nargin > 2) + print_usage (); + elseif (ndims (img) != 2) + error("imgradient: IMG must be a 2 dimensional matrix"); + endif + + if (ischar (method)) + [gradX, gradY] = imgradientxy (img, method); + else + ## we already got gX and gY, just confirm it's good data + if (! size_equal (img, method)) + error("imgradient: GX and GY must be of equal size") + endif + gradX = img; + gradY = method; + endif + + gradMag = sqrt (gradX.^2 + gradY.^2); + + if (nargout > 1) + ## Why imgradient invert vertical when computing the angle + ## Use atan2(-gy,gx)*pi/180. See http://stackoverflow.com/questions/18549015 + gradDir = atan2d (-gradY, gradX); + endif + +endfunction + +%!test +%! A = [0 1 0 +%! 1 1 1 +%! 0 1 0]; +%! +%! [gMag, gDir] = imgradient (A); +%! assert (gMag,[sqrt(18) 4 sqrt(18); 4 0 4; sqrt(18),4,sqrt(18)]); +%! assert (gDir,[-45 -90 -135; -0 -0 -180; 45 90 135]); +%! +%! ## the following just test if passing gx and gy separately gets +%! ## us the same as the image and method though imgradient +%! [gxSobel, gySobel] = imgradientxy (A, "Sobel"); +%! [gxPrewitt, gyPrewitt] = imgradientxy (A, "Prewitt"); +%! [gxCd, gyCd] = imgradientxy (A, "CentralDifference"); +%! [gxId, gyId] = imgradientxy (A, "IntermediateDifference"); +%! +%! assert (imgradient (A), +%! imgradient (gxSobel, gySobel)); +%! assert (imgradient (A, "Sobel"), +%! imgradient (gxSobel, gySobel)); +%! assert (imgradient (A, "Prewitt"), +%! imgradient(gxPrewitt, gyPrewitt)); +%! assert (imgradient (A, "CentralDifference"), +%! imgradient (gxCd, gyCd)); +%! assert (imgradient (A, "IntermediateDifference"), +%! imgradient (gxId, gyId)); +
--- a/inst/imgradientxy.m +++ b/inst/imgradientxy.m @@ -1,119 +1,133 @@ -## Copyright (C) 2013 Brandon Miles <brandon.miles7 at gmail.com> -## -## 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 3 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, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{gradX}, @var{gradY}] =} imgradientxy (@var{image}, @var{method}) -## Compute the x and y gradients of an image using various methods. The first input @var{image} is the gray -## scale image to compute the edges on. The second input @var{method} controls the method used to calculate -## the gradients. The first output @var{gradX} returns the gradient in the x direction. The second output -## @var{gradY} returns the gradient in the y direction. -## -## The @var{method} input argument can be any of the following strings (the default -## value is "Sobel") -## -## @table @asis -## @item "Sobel" -## Calculates the gradient in @var{image} using the Sobel approximation to the -## derivatives. -## -## @item "Prewitt" -## Calculates the gradient in @var{image} using the Prewitt approximation to the -## derivatives. This method works just like "Sobel" except a different approximation of -## the gradient is used. -## -## @item "Central Difference" -## Calculates the gradient in @var{image} using the central difference approximation to the -## derivatives: (x(i-1) - x(i+1))/2. -## -## @item "Intermediate Difference" -## Calculates the gradient in @var{image} using the intermediate difference approximation to -## the derivatives: x(i) - x(i+1). -## -## @end table -## -## @seealso{edge, gradientxy} -## @end deftypefn - -function [gradX gradY] = imgradientxy (image, method) - ## Get the image - if (nargin == 0) - error("gradientxy: not enough input arguments"); - endif - if ( ndims(image) > 2 ) - error("gradientxy: first input must be a gray-scale image"); - endif - - ## Get the method - if (nargin == 1) - method = "Sobel"; - endif - if (!ischar(method)) - error("gradientxy: second argument must be a string"); - endif - method = lower(method); - - switch(method) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %% Sobel, Prewitt - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - case {'sobel','prewitt'} - ker = fspecial(method); # horizontal - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %% Central Difference - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - case {'centraldifference'} - ker = [0.5; 0; -0.5]; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %% Intermediate Difference - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - case {'intermediatedifference'} - ker = [1; -1]; - - otherwise - error('Unrecognized method'); - end - - gradX = conv2(image, ker', 'same'); - gradY = conv2(image, ker, 'same'); - -endfunction - -%% run tests -%!A = [0 1 0; 1 1 1; 0 1 0]; -%![gxSobel, gySobel] = imgradientxy(A); -%![gxSobel2, gySobel2] = imgradientxy(A,'Sobel'); -%![gxPrewitt,gyPrewitt] = imgradientxy(A,'Prewitt'); -%![gxCd,gyCd] = imgradientxy(A,'CentralDifference'); -%![gxId,gyId] = imgradientxy(A,'IntermediateDifference'); -%% -%!assert(gxSobel,gxSobel2); -%!assert(gySobel,gySobel2); -%% -%% Test Sobel -%!assert(gxSobel,[3 0 -3; 4 0 -4; 3 0 -3]); -%!assert(gySobel,[3 4 3; 0 0 0; -3 -4 -3]); -%% -%% Test Prewitt -%!assert(gxPrewitt,[2 0 -2; 3 0 -3; 2 0 -2]); -%!assert(gyPrewitt,[2 3 2; 0 0 0; -2 -3 -2]); -%% -%% Test Central Difference -%!assert(gxCd,[0.5 0 -0.5; 0.5 0 -0.5; 0.5 0 -0.5]); -%!assert(gyCd,[0.5 0.5 0.5; 0 0 0; -0.5 -0.5 -0.5]); -%% -%!assert(gxId,[1 -1 0; 0 0 -1; 1 -1 0]); -%!assert(gyId,[1 0 1; -1 0 -1; 0 -1 0]); +## Copyright (C) 2013 Brandon Miles <brandon.miles7@gmail.com> +## +## 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 3 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, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{gradX}, @var{gradY}] =} imgradientxy (@var{img}) +## @deftypefnx {Function File} {[@var{gradX}, @var{gradY}] =} imgradientxy (@var{img}, @var{method}) +## Compute the x and y gradients of an image using various methods. +## +## The first input @var{img} is the gray scale image to compute the edges +## on. The second input @var{method} controls the method used to calculate +## the gradients. +## +## The first output @var{gradX} returns the gradient in the x direction. +## The second output @var{gradY} returns the gradient in the y direction. +## +## The @var{method} input argument can be any of the following strings: +## +## @table @asis +## @item @qcode{"sobel"} (default) +## Calculates the gradient using the Sobel approximation to the +## derivatives. +## +## @item @qcode{"prewitt"} +## Calculates the gradient using the Prewitt approximation to the +## derivatives. This method works just like Sobel except a different +## approximation of the gradient is used. +## +## @item @qcode{"central difference"} +## Calculates the gradient using the central difference approximation to the +## derivatives: @code{(x(i-1) - x(i+1))/2}. +## +## @item @qcode{"intermediate difference"} +## Calculates the gradient in using the intermediate difference approximation +## to the derivatives: @code{x(i) - x(i+1)}. +## +## @end table +## +## @seealso{edge, imgradient} +## @end deftypefn + +function [gradX, gradY] = imgradientxy (img, method = "sobel") + + if (nargin < 1 || nargin > 2) + print_usage (); + elseif (! isgray (img)) + error ("imgradientxy: IMG must be a gray-scale image"); + elseif (! ischar (method)) + error ("imgradientxy: METHOD must be a string"); + endif + + switch (tolower (method)) + case {"sobel", "prewitt"} + ker = fspecial (method); # horizontal + + case {"centraldifference"} + ker = [0.5; 0; -0.5]; + + case {"intermediatedifference"} + ker = [1; -1]; + + otherwise + error("imgradientxy: unrecognized METHOD %s", method); + endswitch + + gradX = conv2 (img, ker', "same"); + if (nargout > 1) + gradY = conv2 (img, ker, "same"); + endif + +endfunction + +%!test +%! A = [0 1 0 +%! 1 1 1 +%! 0 1 0]; +%! +%! [gxSobel, gySobel] = imgradientxy (A); +%! [gxSobel2, gySobel2] = imgradientxy (A, "Sobel"); +%! assert (gxSobel, +%! [ 3 0 -3 +%! 4 0 -4 +%! 3 0 -3]); +%! assert (gySobel, +%! [ 3 4 3 +%! 0 0 0 +%! -3 -4 -3]); +%! +%! ## test default method +%! assert(gxSobel, gxSobel2); +%! assert(gySobel, gySobel2); +%! +%! [gxPrewitt, gyPrewitt] = imgradientxy (A, "Prewitt"); +%! assert (gxPrewitt, +%! [ 2 0 -2 +%! 3 0 -3 +%! 2 0 -2]); +%! assert (gyPrewitt, +%! [ 2 3 2 +%! 0 0 0 +%! -2 -3 -2]); +%! +%! [gxCd, gyCd] = imgradientxy (A, "CentralDifference"); +%! assert (gxCd, +%! [ 0.5 0.0 -0.5 +%! 0.5 0.0 -0.5 +%! 0.5 0.0 -0.5]); +%! assert (gyCd, +%! [ 0.5 0.5 0.5 +%! 0 0 0 +%! -0.5 -0.5 -0.5]); +%! +%! [gxId, gyId] = imgradientxy(A, "IntermediateDifference"); +%! assert (gxId, +%! [ 1 -1 0 +%! 0 0 -1 +%! 1 -1 0]); +%! assert (gyId, +%! [ 1 0 1 +%! -1 0 -1 +%! 0 -1 0]); +