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)