changeset 857:75d6748324de

New functions imgradient and imgradientxy (patch #8265) * imgradient.m, imgradientxy.m: new function files. * INDEX: update list of functions. * NEWS: update list of new functinos for next release.
author Brandon Miles <brandon.miles7@gmail.com>
date Sun, 05 Jan 2014 07:27:06 +0000
parents 4c060d12db5f
children af3c7946534b
files INDEX NEWS inst/imgradient.m inst/imgradientxy.m
diffstat 4 files changed, 239 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/INDEX
+++ b/INDEX
@@ -3,7 +3,6 @@
  edge
  fftconv2
  corr2
- imhist
  mean2
  std2
  entropy
@@ -15,6 +14,9 @@
  houghtf
  hough_line
  hough_circle
+ imgradient
+ imgradientxy
+ imhist
  immaximas
  normxcorr2
  rangefilt
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,8 @@
       checkerboard
       cp2tform
       findbounds
+      imgradient
+      imgradientxy
       impixel
       imtransform
       intlut
new file mode 100644
--- /dev/null
+++ b/inst/imgradient.m
@@ -0,0 +1,115 @@
+## 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
new file mode 100644
--- /dev/null
+++ b/inst/imgradientxy.m
@@ -0,0 +1,119 @@
+## 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]);