Mercurial > forge
changeset 11374:b3170c1ca567 octave-forge
imrotate: move imrotate_Fourier into imrotate
* deprecate direct call to imrotate_Fourier(). The method option
of imrotate() should be used instead.
* make imrotate_Fourier() code a subfunction on the imrotate.m file
* remove subfunction MakeShears() and place it inside the imrotate_Fourier()
code since it was only being called once
* remove call to tic() on imrotate_Fourier()
* remove input check from imrotate_Fourier() since it is now handle by
imrotate()
* update NEWS accordingly
author | carandraug |
---|---|
date | Sat, 12 Jan 2013 14:41:28 +0000 |
parents | e0b85689330f |
children | fde3acd5937a |
files | main/image/NEWS main/image/inst/imrotate.m main/image/inst/imrotate_Fourier.m |
diffstat | 3 files changed, 159 insertions(+), 164 deletions(-) [+] |
line wrap: on
line diff
--- a/main/image/NEWS Fri Jan 11 20:34:25 2013 +0000 +++ b/main/image/NEWS Sat Jan 12 14:41:28 2013 +0000 @@ -10,6 +10,11 @@ tformfwd tforminv + ** The following functions have been deprecated (see their help text + for the recommended alternatives): + + imrotate_Fourier + ** The plot produced by `imhist' is correctly scaled on the X axis so that the colorbar corresponds to the actual intensity of the stems; the given colormarp is used on the colorbar for indexed images; and the stems no
--- a/main/image/inst/imrotate.m Fri Jan 11 20:34:25 2013 +0000 +++ b/main/image/inst/imrotate.m Sat Jan 12 14:41:28 2013 +0000 @@ -1,3 +1,4 @@ +## Copyright (C) 2002 Jeff Orchard <jorchard@cs.uwaterloo.ca> ## Copyright (C) 2004-2005 Justus H. Piater <Justus.Piater@ULg.ac.be> ## ## This program is free software; you can redistribute it and/or modify it under @@ -14,8 +15,8 @@ ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {} imrotate(@var{imgPre}, @var{theta}, @var{method}, @var{bbox}, @var{extrapval}) -## Rotation of a 2D matrix about its center. +## @deftypefn {Function File} {} imrotate (@var{imgPre}, @var{theta}, @var{method}, @var{bbox}, @var{extrapval}) +## Rotate image about its center. ## ## Input parameters: ## @@ -61,7 +62,8 @@ ## not available if Fourier interpolation is used. ## @end deftypefn -function [imgPost, H, valid] = imrotate(imgPre, thetaDeg, interp="nearest", bbox="loose", extrapval=NA) +function [imgPost, H, valid] = imrotate (imgPre, thetaDeg, interp = "nearest", bbox = "loose", extrapval = NA) + ## Check input if (nargin < 2) error("imrotate: not enough input arguments"); @@ -179,6 +181,140 @@ endif endfunction + +function fs = imrotate_Fourier (f, theta, method, bbox) + + if (size (f, 3) != 1) + error("imrotate_Fourier: image argument must be a gray-scale image"); + endif + + # Get original dimensions. + [ydim_orig, xdim_orig] = size(f); + + # This finds the index coords of the centre of the image (indices are base-1) + # eg. if xdim_orig=8, then xcentre_orig=4.5 (half-way between 1 and 8) + xcentre_orig = (xdim_orig+1) / 2; + ycentre_orig = (ydim_orig+1) / 2; + + # Pre-process the angle =========================================================== + # Whichever 90 degree multiple theta is closest to, that multiple of 90 will + # be implemented by rot90. The remainder will be done by shears. + + # This ensures that 0 <= theta < 360. + theta = rem( rem(theta,360) + 360, 360 ); + + # This is a flag to keep track of 90-degree rotations. + perp = 0; + + if ( theta>=0 && theta<=45 ) + phi = theta; + elseif ( theta>45 && theta<=135 ) + phi = theta - 90; + f = rot90(f,1); + perp = 1; + elseif ( theta>135 && theta<=225 ) + phi = theta - 180; + f = rot90(f,2); + elseif ( theta>225 && theta<=315 ) + phi = theta - 270; + f = rot90(f,3); + perp = 1; + else + phi = theta; + endif + + if ( phi == 0 ) + fs = f; + if ( strcmp(bbox,"loose") == 1 ) + return; + else + xmax = xcentre_orig; + ymax = ycentre_orig; + if ( perp == 1 ) + xmax = max([xmax ycentre_orig]); + ymax = max([ymax xcentre_orig]); + [ydim xdim] = size(fs); + xpad = ceil( xmax - (xdim+1)/2 ); + ypad = ceil( ymax - (ydim+1)/2 ); + fs = impad(fs, [xpad,xpad], [ypad,ypad], "zeros"); + endif + xcentre_new = (size(fs,2)+1) / 2; + ycentre_new = (size(fs,1)+1) / 2; + endif + else + + # At this point, we can assume -45<theta<45 (degrees) + phi = phi * pi / 180; + theta = theta * pi / 180; + R = [ cos(theta) -sin(theta) ; sin(theta) cos(theta) ]; + + # Find max of each dimension... this will be expanded for "loose" and "crop" + xmax = xcentre_orig; + ymax = ycentre_orig; + + # If we don't want wrapping, we have to zeropad. + # Cropping will be done later, if necessary. + if ( strcmp(bbox, "wrap") == 0 ) + corners = ( [ xdim_orig xdim_orig -xdim_orig -xdim_orig ; ydim_orig -ydim_orig ydim_orig -ydim_orig ] + 1 )/ 2; + rot_corners = R * corners; + xmax = max([xmax rot_corners(1,:)]); + ymax = max([ymax rot_corners(2,:)]); + + # If we are doing a 90-degree rotation first, we need to make sure our + # image is large enough to hold the rot90 image as well. + if ( perp == 1 ) + xmax = max([xmax ycentre_orig]); + ymax = max([ymax xcentre_orig]); + endif + + [ydim xdim] = size(f); + xpad = ceil( xmax - xdim/2 ); + ypad = ceil( ymax - ydim/2 ); + %f = impad(f, [xpad,xpad], [ypad,ypad], "zeros"); + xcentre_new = (size(f,2)+1) / 2; + ycentre_new = (size(f,1)+1) / 2; + endif + + S1 = S2 = eye (2); + S1(1,2) = -tan(phi/2); + S2(2,1) = sin(phi); + + f1 = imshear(f, 'x', S1(1,2), 'loose'); + f2 = imshear(f1, 'y', S2(2,1), 'loose'); + fs = real( imshear(f2, 'x', S1(1,2), 'loose') ); + %fs = f2; + xcentre_new = (size(fs,2)+1) / 2; + ycentre_new = (size(fs,1)+1) / 2; + endif + + if ( strcmp(bbox, "crop") == 1 ) + + # Crop to original dimensions + x1 = ceil (xcentre_new - xdim_orig/2); + y1 = ceil (ycentre_new - ydim_orig/2); + fs = fs (y1:(y1+ydim_orig-1), x1:(x1+xdim_orig-1)); + + elseif ( strcmp(bbox, "loose") == 1 ) + + # Find tight bounds on size of rotated image + # These should all be positive, or 0. + xmax_loose = ceil( xcentre_new + max(rot_corners(1,:)) ); + xmin_loose = floor( xcentre_new - max(rot_corners(1,:)) ); + ymax_loose = ceil( ycentre_new + max(rot_corners(2,:)) ); + ymin_loose = floor( ycentre_new - max(rot_corners(2,:)) ); + + fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) ); + + endif + + ## Prevent overshooting + if (strcmp(class(f), "double")) + fs(fs>1) = 1; + fs(fs<0) = 0; + endif + +endfunction + %!test %! ## Verify minimal loss across six rotations that add up to 360 +/- 1 deg.: %! methods = { "nearest", "bilinear", "bicubic", "Fourier" }; @@ -208,7 +344,7 @@ %! end %! end -%!#test +%!xtest %! ## Verify exactness of near-90 and 90-degree rotations: %! X = rand(99); %! for angle = [90 180 270] @@ -220,7 +356,7 @@ %! end %! end -%!#test +%!test %! ## Verify preserved pixel density: %! methods = { "nearest", "bilinear", "bicubic", "Fourier" }; %! ## This test does not seem to do justice to the Fourier method...:
--- a/main/image/inst/imrotate_Fourier.m Fri Jan 11 20:34:25 2013 +0000 +++ b/main/image/inst/imrotate_Fourier.m Sat Jan 12 14:41:28 2013 +0000 @@ -14,170 +14,24 @@ ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {} imrotate(@var{M}, @var{theta}, @var{method}, @var{bbox}) +## @deftypefn {Function File} {} imrotate_Fourier (@var{M}, @var{theta}, @var{method}, @var{bbox}) ## Rotation of a 2D matrix. ## -## Applies a rotation of @var{THETA} degrees to matrix @var{M}. +## @emph{This function has been deprecated and will be removed. Instead, use +## @code{imrotate} and select the @code{fourier} method. This function is +## actually just a wrapper to that function.} ## -## The @var{method} argument is not implemented, and is only included for compatibility with Matlab. -## This function uses Fourier interpolation, -## decomposing the rotation matrix into 3 shears. -## -## @var{bbox} can be either 'loose' or 'crop'. -## 'loose' allows the image to grow to accomodate the rotated image. -## 'crop' keeps the same size as the original, clipping any part of the image -## that is moved outside the bounding box. +## @seealso{imrotate} ## @end deftypefn -function fs = imrotate_Fourier(f, theta, method="fourier", bbox="loose") - - ## Input checking - if (nargin < 2) - error("imrotate_Fourier: not enough input arguments"); - endif - [imrows, imcols, tmp] = size(f); - if (tmp != 1) - error("imrotate_Fourier: first input argument must be a gray-scale image"); - endif - if (!isscalar(theta)) - error("imrotate_Fourier: second input argument must be a real scalar"); - endif - - # Get original dimensions. - [ydim_orig, xdim_orig] = size(f); - - # This finds the index coords of the centre of the image (indices are base-1) - # eg. if xdim_orig=8, then xcentre_orig=4.5 (half-way between 1 and 8) - xcentre_orig = (xdim_orig+1) / 2; - ycentre_orig = (ydim_orig+1) / 2; - - # Pre-process the angle =========================================================== - # Whichever 90 degree multiple theta is closest to, that multiple of 90 will - # be implemented by rot90. The remainder will be done by shears. - - # This ensures that 0 <= theta < 360. - theta = rem( rem(theta,360) + 360, 360 ); - - # This is a flag to keep track of 90-degree rotations. - perp = 0; - - if ( theta>=0 && theta<=45 ) - phi = theta; - elseif ( theta>45 && theta<=135 ) - phi = theta - 90; - f = rot90(f,1); - perp = 1; - elseif ( theta>135 && theta<=225 ) - phi = theta - 180; - f = rot90(f,2); - elseif ( theta>225 && theta<=315 ) - phi = theta - 270; - f = rot90(f,3); - perp = 1; - else - phi = theta; - endif - - - - if ( phi == 0 ) - fs = f; - if ( strcmp(bbox,"loose") == 1 ) - return; - else - xmax = xcentre_orig; - ymax = ycentre_orig; - if ( perp == 1 ) - xmax = max([xmax ycentre_orig]); - ymax = max([ymax xcentre_orig]); - [ydim xdim] = size(fs); - xpad = ceil( xmax - (xdim+1)/2 ); - ypad = ceil( ymax - (ydim+1)/2 ); - fs = impad(fs, [xpad,xpad], [ypad,ypad], "zeros"); - endif - xcentre_new = (size(fs,2)+1) / 2; - ycentre_new = (size(fs,1)+1) / 2; - endif - else +function fs = imrotate_Fourier (f, theta, method = "fourier", bbox = "loose") - # At this point, we can assume -45<theta<45 (degrees) - - phi = phi * pi / 180; - theta = theta * pi / 180; - R = [ cos(theta) -sin(theta) ; sin(theta) cos(theta) ]; - - # Find max of each dimension... this will be expanded for "loose" and "crop" - xmax = xcentre_orig; - ymax = ycentre_orig; - - # If we don't want wrapping, we have to zeropad. - # Cropping will be done later, if necessary. - if ( strcmp(bbox, "wrap") == 0 ) - corners = ( [ xdim_orig xdim_orig -xdim_orig -xdim_orig ; ydim_orig -ydim_orig ydim_orig -ydim_orig ] + 1 )/ 2; - rot_corners = R * corners; - xmax = max([xmax rot_corners(1,:)]); - ymax = max([ymax rot_corners(2,:)]); - - # If we are doing a 90-degree rotation first, we need to make sure our - # image is large enough to hold the rot90 image as well. - if ( perp == 1 ) - xmax = max([xmax ycentre_orig]); - ymax = max([ymax xcentre_orig]); - endif - - [ydim xdim] = size(f); - xpad = ceil( xmax - xdim/2 ); - ypad = ceil( ymax - ydim/2 ); - %f = impad(f, [xpad,xpad], [ypad,ypad], "zeros"); - xcentre_new = (size(f,2)+1) / 2; - ycentre_new = (size(f,1)+1) / 2; - endif - - #size(f) - [S1, S2] = MakeShears(phi); - - tic; - f1 = imshear(f, 'x', S1(1,2), 'loose'); - f2 = imshear(f1, 'y', S2(2,1), 'loose'); - fs = real( imshear(f2, 'x', S1(1,2), 'loose') ); - %fs = f2; - xcentre_new = (size(fs,2)+1) / 2; - ycentre_new = (size(fs,1)+1) / 2; - endif - - if ( strcmp(bbox, "crop") == 1 ) - - # Crop to original dimensions - x1 = ceil (xcentre_new - xdim_orig/2); - y1 = ceil (ycentre_new - ydim_orig/2); - fs = fs (y1:(y1+ydim_orig-1), x1:(x1+xdim_orig-1)); - - elseif ( strcmp(bbox, "loose") == 1 ) - - # Find tight bounds on size of rotated image - # These should all be positive, or 0. - xmax_loose = ceil( xcentre_new + max(rot_corners(1,:)) ); - xmin_loose = floor( xcentre_new - max(rot_corners(1,:)) ); - ymax_loose = ceil( ycentre_new + max(rot_corners(2,:)) ); - ymin_loose = floor( ycentre_new - max(rot_corners(2,:)) ); - - %fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) ); - fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) ); - - endif - - ## Prevent overshooting - if (strcmp(class(f), "double")) - fs(fs>1) = 1; - fs(fs<0) = 0; - endif + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "`imrotate_Fourier' has been deprecated in favor of `imrotate (M, theta, \"fourier\")'. This function will be removed from future versions of the `image' package"); + endif + fs = imrotate (f, theta, "fourier", bbox) endfunction - -function [S1, S2] = MakeShears(theta) - S1 = eye(2); - S2 = eye(2); - - S1(1,2) = -tan(theta/2); - S2(2,1) = sin(theta); -endfunction