function [normim, height, width, normtform, xdata, ydata] = imnorm(im)
%
% Implementation of the image normalization part of:
% 1. P. Dong, J.G. Brankov, N.P. Galatsanos, Y. Yang, and F. Davoine,
% "Digital Watermarking Robust to Geometric Distortions," IEEE Trans.
% Image Processing, Vol. 14, No. 12, pp. 2140-2150, 2005.
% 2. P. Dong and N.P. Galatsanos, "Affine Transformation Resistant
% Watermarking Based on Image Normalization," Int. Conf. Image
% Processing, pp. 489-492, 2002.
%
% Input:
% im: input grayscale image
%
% Output:
% normim: normalized image of class double
% height, width: actual size of the input image (without black border)
% normtform: tform of the normalization
% xdata, ydata: spatial coordinates of the normalized image
%
% Copyright (c), Yuan-Liang Tang
% Associate Professor
% Department of Information Management
% Chaoyang University of Technology
% Taichung, Taiwan
% Email: yltang@cyut.edu.tw
% http://www.cyut.edu.tw/~yltang
%
% Permission is hereby granted, free of charge, to any person obtaining
% a copy of this software without restriction, subject to the following
% conditions:
% The above copyright notice and this permission notice should be included
% in all copies or substantial portions of the Software.
%
% The Software is provided "as is", without warranty of any kind.
%
% Created: 5/2/2007
% Last updated: 3/31/2008
%
if ~isa(im, 'double')
im = double(im);
end
[height width] = size(im); % Size of the original image
% Normalization steps:
% 1. Translation invariance: translate coordinate to the image centroid
[cx cy] = imcentroid(im);
tmat = [1 0 0; 0 1 0; -cx -cy 1]; % Translation matrix
mat = tmat;
tform = maketform('affine', mat);
[imt xdata ydata] = imtransform(im, tform, 'XYScale', 1);
%showim(imt, 'Translation', xdata, ydata);
% 2. X-direction shearing invariance
[cx cy] = imcentroid(imt);
u03 = immoment(imt, 0, 3, cx, cy);
u12 = immoment(imt, 1, 2, cx, cy);
u21 = immoment(imt, 2, 1, cx, cy);
u30 = immoment(imt, 3, 0, cx, cy);
rts = sort(roots([u03, 3*u12, 3*u21, u30]));
if isreal(rts) % If all roots are real: choose the median one
beta = rts(2);
else % Else: choose the real one
for i = 1:3
if isreal(rts(i))
beta = rts(i);
break
end
end
end
xmat = [1 0 0; beta 1 0; 0 0 1]; % X-shearing matrix
mat = mat*xmat;
tform = maketform('affine', mat);
[imtx xdata ydata] = imtransform(im, tform, 'XYScale', 1);
%showim(imtx, 'Xshearing', xdata, ydata);
% 3. Y-direction shearing invariance
[cx cy] = imcentroid(imtx);
u11 = immoment(imtx, 1, 1, cx, cy);
u20 = immoment(imtx, 2, 0, cx, cy);
gamma = -u11/u20;
ymat = [1 gamma 0; 0 1 0; 0 0 1]; % Y-shearing matrix
mat = mat*ymat;
tform = maketform('affine', mat);
[imtxy xdata ydata] = imtransform(im, tform, 'XYScale', 1);
%showim(imtxy, 'Yshearing', xdata, ydata);
% 4. Anisotropic scaling invariance
% Scale the supported area of the image to the fixed size of [512 512]
[r c] = find(imtxy);
alpha = 512/(max(c)-min(c)+1);
delta = 512/(max(r)-min(r)+1);
smat = [alpha 0 0; 0 delta 0; 0 0 1]; % Scaling matrix
% Ensure u50>0 and u05>0
tmpmat = mat*smat;
tform = maketform('affine', tmpmat);
[imtxys xdata ydata] = imtransform(im, tform, 'XYScale', 1);
[cx cy] = imcentroid(imtxys);
if immoment(imtxys, 5, 0, cx, cy) < 0
alpha = -alpha;
end
if immoment(imtxys, 0, 5, cx, cy) < 0
delta = -delta;
end
smat = [alpha 0 0; 0 delta 0; 0 0 1]; % Scaling matrix
mat = mat*smat;
tform = maketform('affine', mat);
[imtxys xdata ydata] = imtransform(im, tform, 'XYScale', 1);
%showim(imtxys, 'Scaling', xdata, ydata);
% 5. Rotation invariance
[cx cy] = imcentroid(imtxys);
u30 = immoment(imtxys, 3, 0, cx, cy);
u21 = immoment(imtxys, 2, 1, cx, cy);
u12 = immoment(imtxys, 1, 2, cx, cy);
u03 = immoment(imtxys, 0, 3, cx, cy);
phi = atan2(u30+u12, u03+u21);
rmat = [cos(phi) sin(phi) 0; -sin(phi) cos(phi) 0; 0 0 1]; % Rotation matrix
% Ensure u03+u21>0
tmpmat = mat*rmat;
tform = maketform('affine', tmpmat);
[imtxysr xdata ydata] = imtransform(im, tform, 'XYScale', 1);
[cx cy] = imcentroid(imtxysr);
u03 = immoment(imtxysr, 0, 3, cx, cy);
u21 = immoment(imtxysr, 2, 1, cx, cy);
if u03+u21<0
phi = phi+pi;
rmat = [cos(phi) sin(phi) 0; -sin(phi) cos(phi) 0; 0 0 1]; % Rotation matrix
end
mat = mat*rmat;
% 6. Perform overall transformation at once
normtform = maketform('affine', mat);
[normim xdata ydata] = imtransform(im, normtform, 'XYScale', 1);
showim(normim, 'Normalized', xdata, ydata);
function [cx, cy] = imcentroid(im)
% Compute image centroid
cx = immoment(im, 1, 0);
cy = immoment(im, 0, 1);
function m = immoment(im, p, q, cx, cy)
% Compute image moment
[y x v] = find(im);
if nargin == 5
x = x - cx;
y = y - cy;
end
m = sum(x.^p .* y.^q .* v)/sum(v);
function showim(im, ttl, xdata, ydata)
figure, imshow(im, [], 'XData', xdata, 'YData', ydata), title(ttl);
impixelinfo, axis on, axis([xdata ydata]);