function out=distort(inp,distortion,base) %DISTORT distort image. % DISTORT distorts an image by the specified amount. % % OUT = DISTORT( INP , DISTORTION) returns an image which is the same % size as the input image INP, but which has been distorted by the % amount DISTORTION. If DISTORTION=0, the output image is the same % as the input. If DISTORTION<0 then the center of the image is magnified % and the sides bow outward. For DISTORTION>0, the center of the image % shrinks and the sides bow inward. % % OUT = DISTORT( INP, DISTORTION, BASE) zooms the final image by % the factor BASE. % % If no output is specified, the distorted image is displayed. % % For example, DISTORT( INP, 0.2) displays the image with 20% distortion. % % Class Support % ------------- % The input image can be of class uint8 or double. The output % image is of the same class as the input image. % John Loomis 25 Feb 2000 error(nargchk(2,3,nargin)); % Check for 2 input arguments. [vlen,hlen,colors]=size(inp); % Size of input image. % Define output image as same type as input (double or uint8). output=zeros(vlen,hlen,colors); if isa(inp,'uint8') output=im2uint8(output); end; xcen=hlen/2.0; % Horizontal center, in pixels. ycen=vlen/2.0; % Vertical center, in pixels. ds = 4.0/(hlen+vlen); % intermediate circle (inscribed in square) %ds = 2.0/min(hlen,vlen); % inscribed circle %ds = 2.0/sqrt(hlen^2+vlen^2); % circumscribed circle % Base magnification factor. if (nargin<3) if (distortion<0.0) rbase = min(hlen,vlen)*ds/2; else rbase = sqrt(hlen^2+vlen^2)*ds/2; end; base = 1.0/(1.0+distortion*rbase^2); end; % x and y are arrays whose elements are x and y positions relative to the % center, normalized to 1 or -1 at the edges. [x,y]=meshgrid(linspace(0.5-xcen,hlen-0.5-xcen,hlen)*ds,linspace(0.5-ycen,vlen-0.5-ycen,vlen)*ds); rf = sqrt(x.^2+y.^2); % Normalized dist. from center. m = base*mag(rf/base,distortion); % Magnification as function of final radius nx=round(xcen+x./(ds*m)); % Array of distorted x indices. ny=round(ycen+y./(ds*m)); % Array of distorted y indices. % Look for out-of-range indices for input image. bad = find(nx<1 | nx>hlen | ny<1 | ny>vlen); % Set to an arbitrary in-range value. nx(bad) = 1; ny(bad) = 1; % reshape arrays as one-dimensional vectors inp = reshape(inp,vlen*hlen,colors); output = reshape(output,vlen*hlen,colors); idx = reshape(ny+(nx-1)*vlen,1,vlen*hlen); % set output image to indexed values from input image output = inp(idx,:); % set out-of-range values to black output(bad,:)=0; % restore output to two-dimensional matrix output = reshape(output,vlen,hlen,colors); % If no output argument was given, display result. if nargout==0 imshow(output); else out=output; end; function m = mag(rfinal,distortion) % MAG calculates the magnification at a specified radius in the % output image. % % rfinal = mag * rinput % where mag = 1.0 + distortion * rinput^2 % % Given rfinal, find rinput and then calculate and return the magnification. % % This is a cubic equation of the form rfinal = rinput + distortion * rinput^3 % which can be solved analytically. However, Newton's method converges to the % solution in about three iterations and the resulting calculation avoids the % use of cube roots. % % % no valid inverse solution exists beyond rmax (r' vs r has horizontal slope) % so we limit the range of rfinal and later set the magnification to near zero. % if (distortion<0.0) rmax = 2/sqrt(-27.0*distortion); idx = find(rfinal>rmax); rfinal(idx)=rmax; end; r = rfinal; % initial value for i=1:3 rsq = r.^2; r = (rfinal + 2*distortion*rsq.*r)./(1+3*distortion*rsq); end; m = 1.0+distortion*r.^2; if (distortion<0.0) m(idx)=0.001; end