1## Copyright (C) 2013 Brandon Miles <brandon.miles7@gmail.com>
2##
3## This program is free software; you can redistribute it and/or modify it
4## under the terms of the GNU General Public License as published by
5## the Free Software Foundation; either version 3 of the License, or
6## (at your option) any later version.
7##
8## This program is distributed in the hope that it will be useful,
9## but WITHOUT ANY WARRANTY; without even the implied warranty of
10## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11## GNU General Public License for more details.
12##
13## You should have received a copy of the GNU General Public License
14## along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16## -*- texinfo -*-
17## @deftypefn  {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{img})
18## @deftypefnx {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{img}, @var{method})
19## @deftypefnx {Function File} {[@var{gradMag}, @var{gradDir}] =} imgradient (@var{gx}, @var{gy})
20## Compute the gradient magnitude and direction in degrees for an image.
21##
22## These are computed from the @var{gx} and @var{xy} gradients using
23## @code{imgradientxy}.  The first input @var{img} is a gray scale image to
24## compute the edges on.  The second input @var{method} controls the method
25## used to calculate the gradients.  Alternatively the first input @var{gx}
26## can be the x gradient and the second input @var{gy} can be the y gradient.
27##
28## The first output @var{gradMag} returns the magnitude of the gradient.
29## The second output @var{gradDir} returns the direction in degrees.
30##
31## The @var{method} input argument must be a string specifying one of the
32## methods supported by @code{imgradientxy}.
33##
34## @seealso{edge, imgradientxy}
35## @end deftypefn
36
37function [gradMag, gradDir] = imgradient (img, method = "sobel")
38
39  if (nargin < 1 || nargin > 2)
40    print_usage ();
41  elseif (ndims (img) != 2)
42    error("imgradient: IMG must be a 2 dimensional matrix");
43  endif
44
45  if (ischar (method))
46    [gradX, gradY] = imgradientxy (img, method);
47  else
48    ## we already got gX and gY, just confirm it's good data
49    if (! size_equal (img, method))
50      error("imgradient: GX and GY must be of equal size")
51    endif
52    gradX = img;
53    gradY = method;
54  endif
55
56  gradMag = sqrt (gradX.^2 + gradY.^2);
57
58  if (nargout > 1)
59    ## Why imgradient invert vertical when computing the angle
60    ## Use atan2(-gy,gx)*pi/180. See http://stackoverflow.com/questions/18549015
61    gradDir = atan2d (-gradY, gradX);
62  endif
63
64endfunction
65
66%!test
67%! A = [0 1 0
68%!      1 1 1
69%!      0 1 0];
70%!
71%! [gMag, gDir] = imgradient (A);
72%! assert (gMag,[sqrt(18) 4 sqrt(18); 4 0 4; sqrt(18),4,sqrt(18)]);
73%! assert (gDir,[-45 -90 -135; -0 -0 -180; 45 90 135]);
74%!
75%! ## the following just test if passing gx and gy separately gets
76%! ## us the same as the image and method though imgradient
77%! [gxSobel, gySobel] = imgradientxy (A, "Sobel");
78%! [gxPrewitt, gyPrewitt] = imgradientxy (A, "Prewitt");
79%! [gxCd, gyCd] = imgradientxy (A, "CentralDifference");
80%! [gxId, gyId] = imgradientxy (A, "IntermediateDifference");
81%!
82%! assert (imgradient (A),
83%!         imgradient (gxSobel, gySobel));
84%! assert (imgradient (A, "Sobel"),
85%!         imgradient (gxSobel, gySobel));
86%! assert (imgradient (A, "Prewitt"),
87%!         imgradient(gxPrewitt, gyPrewitt));
88%! assert (imgradient (A, "CentralDifference"),
89%!         imgradient (gxCd, gyCd));
90%! assert (imgradient (A, "IntermediateDifference"),
91%!         imgradient (gxId, gyId));
92
93