Custom Spatial Transforms
From MATLAB Techniques for Image Processing by Steve Eddins.
Contents
How function handles work
f = @sin
f = @sin
f(1)
ans = 0.8415
f(pi/2)
ans = 1
integral(f,0,pi)
ans = 2.0000
You can define your own spatial transform using maketform('custom', ...) and supplying function handles for doing the inverse and (optionally) the forward transform.
Let's start with simple transform that just swaps the coordinates (u = y, v = x).
type transposeTform
function tform = transposeTform % From MATLAB Techniques for Image Processing by Steve Eddins % Copyright 2012-2014 The MathWorks, Inc. % This is a two-dimensional transform. ndims_in = 2; ndims_out = 2; % No extra data is needed to perform the transform. tdata = []; tform = maketform('custom',ndims_in,ndims_out, ... @T,@T_inv,tdata); %=================================================================== function xy = T(uv,~) xy = uv(:,[2 1]); %=================================================================== function uv = T_inv(xy,~) uv = xy(:,[2 1]);
rgb = imread('liftingbody.png');
tform = transposeTform
tform = ndims_in: 2 ndims_out: 2 forward_fcn: @T inverse_fcn: @T_inv tdata: []
rgb2 = imtransform(rgb,tform);
subplot(1,2,1), imshow(rgb), xlabel('Image courtesy of NASA')
subplot(1,2,2), imshow(rgb2)

"Einstein Effect" See Beyond Photography: The Digital Darkroom, Gerard J. Holzmann, Prentice Hall, 1988, http://spinroot.com/pico/
type einsteinTform
function tform = einsteinTform % From MATLAB Techniques for Image Processing by Steve Eddins % Copyright 2012-2014 The MathWorks, Inc. tform = maketform('custom',2,2,[],@T_inv,[]); %=================================================================== function uv = T_inv(xy,~) x = xy(:,1) - 150; y = xy(:,2) - 150; [a_out,r_out] = cart2pol(x,y); a_in = a_out; r_in = sqrt(r_out*212); [u,v] = pol2cart(a_in,r_in); uv = [u + 150,v + 150];
rgb = imread('moler.jpg');
rgb2 = imtransform(rgb,einsteinTform);
subplot(1,2,1), imshow(rgb)
subplot(1,2,2), imshow(rgb2)

Let's try a custom spatial transform with a more complicated use of extra data.
type randomWalkShearTform
function tform = randomWalkShearTform(image_size) % From MATLAB Techniques for Image Processing by Steve Eddins % Copyright 2012-2014 The MathWorks, Inc. M = image_size(1); N = image_size(2); tdata.xshift = cumsum(((rand(M,1) < 0.5)*4) - 2); tdata.yshift = cumsum(((rand(N,1) < 0.5)*4) - 2); tdata.M = M; tdata.N = N; tform = maketform('custom',2,2,[],@T_inv,tdata); %==================================================================== function uv = T_inv(xy,tform) x = xy(:,1); y = xy(:,2); x = round(x); x = min(max(x,1),tform.tdata.N); y = round(y); y = min(max(y,1),tform.tdata.M); u = x + tform.tdata.xshift(y); v = y + tform.tdata.yshift(x); uv = [u,v];
rgb = imread('loren.jpg');
rgb2 = imtransform(rgb,randomWalkShearTform(size(rgb)));
subplot(1,2,1),imshow(rgb)
subplot(1,2,2),imshow(rgb2)

type blockShiftTform
function tform = blockShiftTform(image_size) % From MATLAB Techniques for Image Processing by Steve Eddins % Copyright 2012-2014 The MathWorks, Inc. M = image_size(1); N = image_size(2); block_sizes = 8:4:32; max_shift = 32; yshift = zeros(N,1); xshift = zeros(M,1); dx = 0; for x = 1:N if dx == 0 % Choose a new shift and a block size. r = round(2*max_shift*(rand - 0.5)); P = numel(block_sizes); block_size_index = floor(P*rand) + 1; dx = block_sizes(block_size_index); else % Still in same block. Decrement block counter. dx = dx - 1; end yshift(x) = r; end dy = 0; for y = 1:M if dy == 0 % Choose a new shift and a block size. r = round(2*max_shift*(rand - 0.5)); P = numel(block_sizes); block_size_index = floor(P*rand) + 1; dy = block_sizes(block_size_index); else % Still in same block. Decrement block counter. dy = dy - 1; end xshift(y) = r; end tdata.xshift = xshift; tdata.yshift = yshift; tdata.M = M; tdata.N = N; tform = maketform('custom',2,2,[],@T_inv,tdata); function uv = T_inv(xy,tform) x = xy(:,1); y = xy(:,2); x = round(x); x = min(max(x,1),tform.tdata.N); y = round(y); y = min(max(y,1),tform.tdata.M); u = x + tform.tdata.xshift(y); v = y + tform.tdata.yshift(x); uv = [u,v];
rgb = imread('jnl.jpg');
rgb2 = imtransform(rgb,blockShiftTform(size(rgb)));
subplot(1,2,1), imshow(rgb)
subplot(1,2,2), imshow(rgb2)

Finally, let's go back to polar coordinates and apply a twist by varying the angle in proportion to the radius.
type twistedTform
function tform = twistedTform(xc,yc,S) % From MATLAB Techniques for Image Processing by Steve Eddins % Copyright 2012-2014 The MathWorks, Inc. tdata.xc = xc; tdata.yc = yc; tdata.S = S; tform = maketform('custom',2,2,[],@T_inv,tdata); function uv = T_inv(xy,tform) xc = tform.tdata.xc; yc = tform.tdata.yc; S = tform.tdata.S; x = xy(:,1) - xc; y = xy(:,2) - yc; [a_output_space,r_output_space] = cart2pol(x,y); r_input_space = r_output_space; a_input_space = ((a_output_space*180/pi) + r_output_space*S)*pi/180; [u,v] = pol2cart(a_input_space,r_input_space); uv = [u + xc, v + yc];
rgb = imread('eddins.jpg');
rgb2 = imtransform(rgb,twistedTform(185,255,1));
subplot(1,2,1), imshow(rgb)
subplot(1,2,2), imshow(rgb2)
