The answer is everything here is working fine, imrotate IS rotating about the center of the input image, and imregtform is correctly recovering the registration that maps the moving image to the fixed image. The issues we have here are artifacts of coordinate system conventions and the way imshowpair is being used.
To start, take a look at the result of overlaying the registered image from your example with the original image:
I2D = zeros(256, 256);
i0 = 40;
for i = 71:230
I2D(i-15,i0:i+10) = 1;
end
I2D(128:130,128:130)=0;
I2DT = imrotate(I2D, 13);
imshowpair(I2D, I2DT);
title('original and transformed image');
[optimizer, metric] = imregconfig('monomodal');
tform = imregtform(I2DT,I2D,'affine',optimizer,metric);
Tmatrix = tform.T;
I2DT_reg = imwarp(I2DT,tform,'OutputView',imref2d(size(I2D)));
figure, imshowpair(I2DT_reg,I2D)
Looks good right?
Here are a couple of observations that might be helpful:
1) Rotation about the center of an image is NOT defined by an elemental affine matrix with a zero translation, except for the special case where the center of the input image is aligned with the origin (0,0). In all other orientations of the input image, including the default coordinate system assumed by MATLAB in IMROTATE in which the first pixel is centered at location 1,1 and the last pixel is centered at Colmax,Rowmax, this is not the case.
One way to define an equivalent affine operation to what imrotate is doing is to create a composite affine transformation in which you do three operations: 1) Translate the center of the image to the origin. 2) Rotate by desired angle. 3) Translate the center of the image back to it's original location.
Rdefault = imref2d(size(I2D));
tX = mean(Rdefault.XWorldLimits);
tY = mean(Rdefault.YWorldLimits);
tTranslationToCenterAtOrigin = [1 0 0; 0 1 0; -tX -tY,1];
theta = 10;
tRotation = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1];
tTranslationBackToOriginalCenter = [1 0 0; 0 1 0; tX tY,1];
tformCenteredRotation = tTranslationToCenterAtOrigin*tRotation*tTranslationBackToOriginalCenter;
tformCenteredRotation = affine2d(tformCenteredRotation);
[out,Rout] = imwarp(I2D,tformCenteredRotation);
imshow(out,Rout)
Note that this transformation has a translation component, and that this is expected.
2) When you are testing the center of rotation and visualizing this using imshowpair, the reason the centers don't line up is that you aren't passing sufficient spatial referencing information to imshowpair. By default, imshowpair aligns the upper left corners of two input image unless the optional spatial referencing arguments are passed in which defined where each image is. That is why it appears that the center is not preserved.
Best Answer