Vitor Rangel
Vitor Rangel

Reputation: 363

How to measure the rotation of a image in MATLAB?

I have two images. One is the original, and the another is rotated.

Original Image

Now, I need to discover the angle that the image was rotated. Until now, I thought about discovering the centroids of each color (as every image I will use has squares with colors in it) and use it to discover how much the image was rotated, but I failed.

I'm using this to discover the centroids and the color in the higher square in the image:

i = rgb2gray(img);
bw = im2bw(i,0.01);
s = regionprops(bw,'Centroid');
centroids = cat(1, s.Centroid);
colors = impixel(img,centroids(1),centroids(2));
top = max(centroids);
topcolor = impixel(img,top(1),top(2));

Upvotes: 4

Views: 4389

Answers (3)

Maurits
Maurits

Reputation: 2114

I would take a variant to the above mentioned approach:

% Crude binarization method to knock out background and retain foreground
% features. Note one looses the cube in the middle
im = im > 1

Enter image description here

Then I would get the 2D autocorrelation:

acf = normxcorr2(im, im);

Enter image description here

From this result, one can easily detect the peaks, and as rotation carries into the autocorrelation function (ACF) domain, one can ascertain the rotation by matching the peaks between the original ACF and the ACF from the rotated image, for example using the so-called Hungarian algorithm.

Upvotes: 1

Dr. belisarius
Dr. belisarius

Reputation: 61026

If you can identify a color corresponding to only one component it is easier to:

  1. Calculate the centroids for each image
  2. Calculate the mean of the centroids (in x and y) for each image. This is the "center" of each image
  3. Get the red component color centroid (in your example) for each image
  4. Subtract the mean of the centroids for each image from the red component color centroid for each image
  5. Calculate the ArcTan2 for each of the vectors calculated in 4), and subtract the angles. That is your result.

If you have more than one figure of each color, you need to calculate all possible combinations for the rotation and then select the one that is compatible with the other possible rotations.

I could post the code in Mathematica, if you think it is useful.

Upvotes: 1

Amro
Amro

Reputation: 124563

You can detect the corners of one of the colored rectangles in both the image and the rotated version, and use these as control points to infer the transformation between the two images (like in image registration) using the CP2TFORM function. We can then compute the angle of rotation from the affine transformation matrix:

Here is an example code:

%# read first image (indexed color image)
[I1 map1] = imread('https://i.sstatic.net/LwuW3.png');

%# constructed rotated image
deg = -15;
I2 = imrotate(I1, deg, 'bilinear', 'crop');

%# find blue rectangle
BW1 = (I1==2);
BW2 = imrotate(BW1, deg, 'bilinear', 'crop');

%# detect corners in both
p1 = corner(BW1, 'QualityLevel',0.5);
p2 = corner(BW2, 'QualityLevel',0.5);

%# sort corners coordinates in a consistent way (counter-clockwise)
p1 = sortrows(p1,[2 1]);
p2 = sortrows(p2,[2 1]);
idx = convhull(p1(:,1), p1(:,2)); p1 = p1(idx(1:end-1),:);
idx = convhull(p2(:,1), p2(:,2)); p2 = p2(idx(1:end-1),:);

%# make sure we have the same number of corner points
sz = min(size(p1,1),size(p2,1));
p1 = p1(1:sz,:); p2 = p2(1:sz,:);

%# infer transformation from corner points
t = cp2tform(p2,p1,'nonreflective similarity');    %# 'affine'

%# rotate image to match the other
II2 = imtransform(I2, t, 'XData',[1 size(I1,2)], 'YData',[1 size(I1,1)]);

%# recover affine transformation params (translation, rotation, scale)
ss = t.tdata.Tinv(2,1);
sc = t.tdata.Tinv(1,1);
tx = t.tdata.Tinv(3,1);
ty = t.tdata.Tinv(3,2);
translation = [tx ty];
scale = sqrt(ss*ss + sc*sc);
rotation = atan2(ss,sc)*180/pi;

%# plot the results
subplot(311), imshow(I1,map1), title('I1')
hold on, plot(p1(:,1),p1(:,2),'go')
subplot(312), imshow(I2,map1), title('I2')
hold on, plot(p2(:,1),p2(:,2),'go')
subplot(313), imshow(II2,map1)
title(sprintf('recovered angle = %g',rotation))

screenshot

Upvotes: 3

Related Questions