问题描述
我试图在不使用 imrotate 函数的情况下使用 Matlab 旋转图像.其实我是用变换矩阵做的,但是还不够好.问题是,旋转后的图片是滑动"的,我用图片告诉你.
I am trying to rotate an image with Matlab without using imrotate function. I actually made it by using transformation matrix.But it is not good enough.The problem is, the rotated image is "sliding".Let me tell you with pictures.
这是我要旋转的图像:
但是当我旋转它时,例如 45 度,它变成这样:
But when I rotate it ,for example 45 degrees, it becomes this:
我在问为什么会这样.这是我的代码,是否有任何数学或编程错误?
I am asking why this is happening.Here is my code,is there any mathematical or programming mistakes about it?
image=torso;
%image padding
[Rows, Cols] = size(image);
Diagonal = sqrt(Rows^2 + Cols^2);
RowPad = ceil(Diagonal - Rows) + 2;
ColPad = ceil(Diagonal - Cols) + 2;
imagepad = zeros(Rows+RowPad, Cols+ColPad);
imagepad(ceil(RowPad/2):(ceil(RowPad/2)+Rows-1),ceil(ColPad/2):(ceil(ColPad/2)+Cols-1)) = image;
degree=45;
%midpoints
midx=ceil((size(imagepad,1)+1)/2);
midy=ceil((size(imagepad,2)+1)/2);
imagerot=zeros(size(imagepad));
%rotation
for i=1:size(imagepad,1)
for j=1:size(imagepad,2)
x=(i-midx)*cos(degree)-(j-midy)*sin(degree);
y=(i-midx)*sin(degree)+(j-midy)*cos(degree);
x=round(x)+midx;
y=round(y)+midy;
if (x>=1 && y>=1)
imagerot(x,y)=imagepad(i,j); % k degrees rotated image
end
end
end
figure,imagesc(imagerot);
colormap(gray(256));
推荐答案
图像中有孔洞的原因是因为您要计算 imagepad
imagerot
中每个像素在 imagerot
中的位置/代码>.您需要以相反的方式进行计算.也就是说,对于 imagerot
中的每个像素,在 imagepad
中进行插值.为此,您只需要应用逆变换,在旋转矩阵的情况下,它只是矩阵的转置(只需更改每个 sin
上的符号并以另一种方式平移).
The reason you have holes in your image is because you are computing the location in imagerot
of each pixel in imagepad
. You need to do the computation the other way around. That is, for each pixel in imagerot
interpolate in imagepad
. To do this, you just need to apply the inverse transform, which in the case of a rotation matrix is just the transpose of the matrix (just change the sign on each sin
and translate the other way).
在imagerot
中循环像素:
imagerot=zeros(size(imagepad)); % midx and midy same for both
for i=1:size(imagerot,1)
for j=1:size(imagerot,2)
x= (i-midx)*cos(rads)+(j-midy)*sin(rads);
y=-(i-midx)*sin(rads)+(j-midy)*cos(rads);
x=round(x)+midx;
y=round(y)+midy;
if (x>=1 && y>=1 && x<=size(imagepad,2) && y<=size(imagepad,1))
imagerot(i,j)=imagepad(x,y); % k degrees rotated image
end
end
end
还要注意,你的 midx
和 midy
需要用 size(imagepad,2)
和 size(imagepad,1)
分别,因为第一个维度是指行数(高度),第二个维度是宽度.
Also note that your midx
and midy
need to be calculated with size(imagepad,2)
and size(imagepad,1)
respectively, since the first dimension refers to the number of rows (height) and the second to width.
注意:当您决定采用最近邻以外的插值方案时,同样的方法也适用,如 Rody 的线性插值示例.
NOTE: The same approach applies when you decide to adopt an interpolation scheme other than nearest neighbor, as in Rody's example with linear interpolation.
编辑:我假设您将循环用于演示目的,但实际上不需要循环.这是最近邻插值的示例(您使用的是什么),保持相同大小的图像,但您可以修改它以生成包含整个源图像的更大图像:
EDIT: I'm assuming you are using a loop for demonstrative purposes, but in practice there is no need for loops. Here's an example of nearest neighbor interpolation (what you are using), keeping the same size image, but you can modify this to produce a larger image that includes the whole source image:
imagepad = imread('peppers.png');
[nrows ncols nslices] = size(imagepad);
midx=ceil((ncols+1)/2);
midy=ceil((nrows+1)/2);
Mr = [cos(pi/4) sin(pi/4); -sin(pi/4) cos(pi/4)]; % e.g. 45 degree rotation
% rotate about center
[X Y] = meshgrid(1:ncols,1:nrows);
XYt = [X(:)-midx Y(:)-midy]*Mr;
XYt = bsxfun(@plus,XYt,[midx midy]);
xout = round(XYt(:,1)); yout = round(XYt(:,2)); % nearest neighbor!
outbound = yout<1 | yout>nrows | xout<1 | xout>ncols;
zout=repmat(cat(3,1,2,3),nrows,ncols,1); zout=zout(:);
xout(xout<1) = 1; xout(xout>ncols) = ncols;
yout(yout<1) = 1; yout(yout>nrows) = nrows;
xout = repmat(xout,[3 1]); yout = repmat(yout,[3 1]);
imagerot = imagepad(sub2ind(size(imagepad),yout,xout,zout(:))); % lookup
imagerot = reshape(imagerot,size(imagepad));
imagerot(repmat(outbound,[1 1 3])) = 0; % set background value to [0 0 0] (black)
要将上述修改为线性插值,请计算 XYt
中每个坐标的 4 个相邻像素,并使用分数分量乘积作为权重执行加权求和.我将把它留作练习,因为它只会使我的答案超出你的问题范围.:)
To modify the above to linear interpolation, compute the 4 neighboring pixels to each coordinate in XYt
and perform a weighted sum using the fractional components product as the weights. I'll leave that as an exercise, since it would only serve to bloat my answer further beyond the scope of your question. :)
这篇关于不使用 imrotate 的 Matlab 图像旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!