PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/octave-forge/main/image/inst/imremap.m

#
Objective C | 229 lines | 204 code | 25 blank | 0 comment | 29 complexity | bdb696b70049fb683170f7133a3d5250 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. ## Copyright (C) 2006 S?ren Hauberg
  2. ##
  3. ## This program is free software; you can redistribute it and/or modify
  4. ## it under the terms of the GNU General Public License as published by
  5. ## the Free Software Foundation; either version 2, or (at your option)
  6. ## any later version.
  7. ##
  8. ## This program is distributed in the hope that it will be useful, but
  9. ## WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ## General Public License for more details.
  12. ##
  13. ## You should have received a copy of the GNU General Public License
  14. ## along with this file. If not, see <http://www.gnu.org/licenses/>.
  15. ## -*- texinfo -*-
  16. ## @deftypefn {Function File} @var{warped} = imremap(@var{im}, @var{XI}, @var{YI})
  17. ## @deftypefnx{Function File} @var{warped} = imremap(@var{im}, @var{XI}, @var{YI}, @var{interp}, @var{extrapval})
  18. ## @deftypefnx{Function File} [@var{warped}, @var{valid} ] = imremap(...)
  19. ## Applies any geometric transformation to the image @var{im}.
  20. ##
  21. ## The arguments @var{XI} and @var{YI} are lookup tables that define the resulting
  22. ## image
  23. ## @example
  24. ## @var{warped}(y,x) = @var{im}(@var{YI}(y,x), @var{XI}(y,x))
  25. ## @end example
  26. ## where @var{im} is assumed to be a continuous function, which is achieved
  27. ## by interpolation. Note that the image @var{im} is expressed in a (X, Y)-coordinate
  28. ## system and not a (row, column) system.
  29. ##
  30. ## The argument @var{interp} selects the used interpolation method, and most be one
  31. ## of the following strings
  32. ## @table @code
  33. ## @item "nearest"
  34. ## Nearest neighbor interpolation.
  35. ## @item "linear"
  36. ## @itemx "bilinear"
  37. ## Bilinear interpolation. This is the default behavior.
  38. ## @item "cubic"
  39. ## @itemx "bicubic"
  40. ## Bicubic interpolation.
  41. ## @end table
  42. ##
  43. ## All values of the result that fall outside the original image will
  44. ## be set to @var{extrapval}. For images of class @code{double} @var{extrapval}
  45. ## defaults to @code{NA} and for other classes it defaults to 0.
  46. ##
  47. ## The optional output @var{valid} is a matrix of the same size as @var{warped}
  48. ## that contains the value 1 in pixels where @var{warped} contains an interpolated
  49. ## value, and 0 in pixels where @var{warped} contains an extrapolated value.
  50. ## @seealso{imperspectivewarp, imrotate, imresize, imshear, interp2}
  51. ## @end deftypefn
  52. function [warped, valid] = imremap(im, XI, YI, interp = "bilinear", extrapval = NA)
  53. ## Check input
  54. if (nargin < 3)
  55. print_usage();
  56. endif
  57. [imrows, imcols, imchannels, tmp] = size(im);
  58. if (tmp != 1 || (imchannels != 1 && imchannels != 3))
  59. error("imremap: first input argument must be an image");
  60. endif
  61. if (!size_equal(XI, YI) || !ismatrix(XI) || ndims(XI) != 2)
  62. error("imremap: XI and YI must be matrices of the same size");
  63. endif
  64. if (!any(strcmpi(interp, {"nearest", "linear", "bilinear", "cubic", "bicubic", "spline"})))
  65. error("imremap: unsupported interpolation method");
  66. endif
  67. if (any(strcmpi(interp, {"bilinear", "bicubic"})))
  68. interp = interp(3:end); # Remove "bi"
  69. endif
  70. interp = lower(interp);
  71. if (!isscalar(extrapval))
  72. error("imremap: extrapolation value must be a scalar");
  73. endif
  74. ## Interpolate
  75. if (imchannels == 1) # Gray
  76. warped = grayinterp(im, XI, YI, interp, NA);
  77. else # rgb image
  78. for i = 3:-1:1
  79. warped(:,:,i) = grayinterp(im(:,:,i), XI, YI, interp, NA);
  80. endfor
  81. endif
  82. valid = !isna(warped);
  83. warped(!valid) = extrapval;
  84. ## Change the class of the results according to the class of the image
  85. c = class(im);
  86. if (strcmpi(c, "uint8"))
  87. warped = uint8(warped);
  88. elseif (strcmpi(c, "uint16"))
  89. warped = uint16(warped);
  90. endif
  91. endfunction
  92. function [warped, valid] = grayinterp(im, XI, YI, interp, extrapval)
  93. if (strcmp(interp, "cubic"))
  94. warped = graybicubic(double(im), XI, YI, NA);
  95. else
  96. warped = interp2(double(im), XI, YI, interp, NA);
  97. endif
  98. valid = !isna(warped);
  99. warped(!valid) = extrapval;
  100. endfunction
  101. ## -*- texinfo -*-
  102. ## @deftypefn {Function File} {@var{zi}=} bicubic (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi})
  103. ## Reference:
  104. ## Image Processing, Analysis, and Machine Vision, 2nd Ed.
  105. ## Sonka et.al.
  106. ## Brooks/Cole Publishing Company
  107. ## ISBN: 0-534-95393-X
  108. ## @seealso{interp2}
  109. ## @end deftypefn
  110. function ZI = graybicubic (Z, XI, YI, extrapval = NA)
  111. ## Allocate output
  112. [X, Y] = meshgrid(1:columns(Z), 1:rows(Z));
  113. [Zr, Zc] = size(XI);
  114. ZI = zeros(Zr, Zc);
  115. ## Find inliers
  116. inside = !( XI < X(1) | XI > X(end) | YI < Y(1) | YI > Y(end) );
  117. ## Scale XI and YI to match indices of Z (not needed when interpolating images)
  118. #XI = (columns(Z)-1) * ( XI - X(1) ) / (X(end)-X(1)) + 1;
  119. #YI = (rows(Z)-1) * ( YI - Y(1) ) / (Y(end)-Y(1)) + 1;
  120. ## Start the real work
  121. K = floor(XI);
  122. L = floor(YI);
  123. ## Coefficients
  124. AY1 = bc((YI-L+1)); AX1 = bc((XI-K+1));
  125. AY0 = bc((YI-L+0)); AX0 = bc((XI-K+0));
  126. AY_1 = bc((YI-L-1)); AX_1 = bc((XI-K-1));
  127. AY_2 = bc((YI-L-2)); AX_2 = bc((XI-K-2));
  128. ## Perform interpolation
  129. sz = size(Z);
  130. %ZI(inside) = AY_2 .* AX_2 .* Z(sym_sub2ind(sz, L+2, K+2)) ...
  131. ZI = AY_2 .* AX_2 .* Z(sym_sub2ind(sz, L+2, K+2)) ...
  132. + AY_2 .* AX_1 .* Z(sym_sub2ind(sz, L+2, K+1)) ...
  133. + AY_2 .* AX0 .* Z(sym_sub2ind(sz, L+2, K)) ...
  134. + AY_2 .* AX1 .* Z(sym_sub2ind(sz, L+2, K-1)) ...
  135. + AY_1 .* AX_2 .* Z(sym_sub2ind(sz, L+1, K+2)) ...
  136. + AY_1 .* AX_1 .* Z(sym_sub2ind(sz, L+1, K+1)) ...
  137. + AY_1 .* AX0 .* Z(sym_sub2ind(sz, L+1, K)) ...
  138. + AY_1 .* AX1 .* Z(sym_sub2ind(sz, L+1, K-1)) ...
  139. + AY0 .* AX_2 .* Z(sym_sub2ind(sz, L, K+2)) ...
  140. + AY0 .* AX_1 .* Z(sym_sub2ind(sz, L, K+1)) ...
  141. + AY0 .* AX0 .* Z(sym_sub2ind(sz, L, K)) ...
  142. + AY0 .* AX1 .* Z(sym_sub2ind(sz, L, K-1)) ...
  143. + AY1 .* AX_2 .* Z(sym_sub2ind(sz, L-1, K+2)) ...
  144. + AY1 .* AX_1 .* Z(sym_sub2ind(sz, L-1, K+1)) ...
  145. + AY1 .* AX0 .* Z(sym_sub2ind(sz, L-1, K)) ...
  146. + AY1 .* AX1 .* Z(sym_sub2ind(sz, L-1, K-1));
  147. ZI(!inside) = extrapval;
  148. endfunction
  149. ## Checks if data is meshgrided
  150. function b = isgriddata(X)
  151. D = X - repmat(X(1,:), rows(X), 1);
  152. b = all(D(:) == 0);
  153. endfunction
  154. ## Checks if data is equally spaced (assumes data is meshgrided)
  155. function b = isequallyspaced(X)
  156. Dx = gradient(X(1,:));
  157. b = all(Dx == Dx(1));
  158. endfunction
  159. ## Computes the interpolation coefficients
  160. function o = bc(x)
  161. x = abs(x);
  162. o = zeros(size(x));
  163. idx1 = (x < 1);
  164. idx2 = !idx1 & (x < 2);
  165. o(idx1) = 1 - 2.*x(idx1).^2 + x(idx1).^3;
  166. o(idx2) = 4 - 8.*x(idx2) + 5.*x(idx2).^2 - x(idx2).^3;
  167. endfunction
  168. ## This version of sub2ind behaves as if the data was symmetrically padded
  169. function ind = sym_sub2ind(sz, Y, X)
  170. Y(Y<1) = 1 - Y(Y<1);
  171. while (any(Y(:)>2*sz(1)))
  172. Y(Y>2*sz(1)) = round( Y(Y>2*sz(1))/2 );
  173. endwhile
  174. Y(Y>sz(1)) = 1 + 2*sz(1) - Y(Y>sz(1));
  175. X(X<1) = 1 - X(X<1);
  176. while (any(X(:)>2*sz(2)))
  177. X(X>2*sz(2)) = round( X(X>2*sz(2))/2 );
  178. endwhile
  179. X(X>sz(2)) = 1 + 2*sz(2) - X(X>sz(2));
  180. ind = sub2ind(sz, Y, X);
  181. endfunction
  182. %!demo
  183. %! ## Generate a synthetic image and show it
  184. %! I = tril(ones(100)) + abs(rand(100)); I(I>1) = 1;
  185. %! I(20:30, 20:30) = !I(20:30, 20:30);
  186. %! I(70:80, 70:80) = !I(70:80, 70:80);
  187. %! figure, imshow(I);
  188. %! ## Resize the image to the double size and show it
  189. %! [XI, YI] = meshgrid(linspace(1, 100, 200));
  190. %! warped = imremap(I, XI, YI);
  191. %! figure, imshow(warped);
  192. %!demo
  193. %! ## Generate a synthetic image and show it
  194. %! I = tril(ones(100)) + abs(rand(100)); I(I>1) = 1;
  195. %! I(20:30, 20:30) = !I(20:30, 20:30);
  196. %! I(70:80, 70:80) = !I(70:80, 70:80);
  197. %! figure, imshow(I);
  198. %! ## Rotate the image around (0, 0) by -0.4 radians and show it
  199. %! [XI, YI] = meshgrid(1:100);
  200. %! R = [cos(-0.4) sin(-0.4); -sin(-0.4) cos(-0.4)];
  201. %! RXY = [XI(:), YI(:)] * R;
  202. %! XI = reshape(RXY(:,1), [100, 100]); YI = reshape(RXY(:,2), [100, 100]);
  203. %! warped = imremap(I, XI, YI);
  204. %! figure, imshow(warped);