在MATLAB中围绕其中心旋转图像矩阵 [英] Rotating an image matrix around its center in MATLAB

查看:2304
本文介绍了在MATLAB中围绕其中心旋转图像矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个2x2矩阵,其中填充了代表平面的值。现在我想在z方向中以三维方式围绕自身旋转平面。为了更好地理解,请参见下图:





<我想知道这是否可以通过一个简单的仿射矩阵,因此我创建了以下简单的脚本:

 %创建一个随机的价值矩阵
A = rand * ones(200,200);

%在图片中设置一个方框
A(50:200-50,50:200-50)= 1;

现在我可以通过这样的旋转矩阵在二维房间中应用变换:

  R = affine2d([1 0 0; .5 1 0; 0 0 1])$ ​​b $ b tform = affine3d(R ); 
transformation = imwarp(A,tform);

然而,这不会产生上面所需的输出,我不太确定如何创建2-D仿射矩阵来创造这种行为。



我猜三维仿射矩阵可以解决这个问题。但是,如果我定义一个三维仿射矩阵,我就不能再使用矩阵的二维表示,因为MATLAB会抛出错误:

 
指定的几何变换为3-D时,输入图像A的维数必须为3。

那么如何使用仿射矩阵对所需的输出进行编码?

解决方案



让我们首先假设您的图像位于查看平面中,并且角落由标准化参考框架描述,使得它们跨越 [ - 1 1] 在每个方向。我们需要首先通过选择视角选择我们想要的透视度,然后计算相机和观察平面之间的距离。大约45度的视角可以模仿正常人类视线的透视感,因此使用观察平面的角来定义圆锥视野的边缘,我们可以如下计算摄像机距离:

  camDist = sqrt(2)./ tand(viewAngle./2); 

现在我们可以使用它来为转换生成一组控制点。我们首先将


Assume I have a 2x2 matrix filled with values which will represent a plane. Now I want to rotate the plane around itself in a 3-D way, in the "z-Direction". For a better understanding, see the following image:

I wondered if this is possible by a simple affine matrix, thus I created the following simple script:

%Create a random value matrix
A = rand*ones(200,200);

%Make a box in the image
A(50:200-50,50:200-50) = 1;

Now I can apply transformations in the 2-D room simply by a rotation matrix like this:

R = affine2d([1 0 0; .5 1 0; 0 0 1])
tform = affine3d(R);
transformed = imwarp(A,tform);

However, this will not produce the desired output above, and I am not quite sure how to create the 2-D affine matrix to create such behavior.

I guess that a 3-D affine matrix can do the trick. However, if I define a 3-D affine matrix I cannot work with the 2-D representation of the matrix anymore, since MATLAB will throw the error:

The number of dimensions of the input image A must be 3 when the
specified geometric transformation is 3-D.

So how can I code the desired output with an affine matrix?

解决方案

The answer from m3tho correctly addresses how you would apply the transformation you want: using fitgeotrans with a 'projective' transform, thus requiring that you specify 4 control points (i.e. 4 pairs of corresponding points in the input and output image). You can then apply this transform using imwarp.

The issue, then, is how you select these pairs of points to create your desired transformation, which in this case is to create a perspective projection. As shown below, a perspective projection takes into account that a viewing position (i.e. "camera") will have a given view angle defining a conic field of view. The scene is rendered by taking all 3-D points within this cone and projecting them onto the viewing plane, which is the plane located at the camera target which is perpendicular to the line joining the camera and its target.

Let's first assume that your image is lying in the viewing plane and that the corners are described by a normalized reference frame such that they span [-1 1] in each direction. We need to first select the degree of perspective we want by choosing a view angle and then computing the distance between the camera and the viewing plane. A view angle of around 45 degrees can mimic the sense of perspective of normal human sight, so using the corners of the viewing plane to define the edge of the conic field of view, we can compute the camera distance as follows:

camDist = sqrt(2)./tand(viewAngle./2);

Now we can use this to generate a set of control points for the transformation. We first apply a 3-D rotation to the corner points of the viewing plane, rotating around the y axis by an amount theta. This rotates them out of plane, so we now project the corner points back onto the viewing plane by defining a line from the camera through each rotated corner point and finding the point where it intersects the plane. I'm going to spare you the mathematical derivations (you can implement them yourself from the formulas in the above links), but in this case everything simplifies down to the following set of calculations:

term1 = camDist.*cosd(theta);
term2 = camDist-sind(theta);
term3 = camDist+sind(theta);
outP = [-term1./term2  camDist./term2; ...
         term1./term3  camDist./term3; ...
         term1./term3 -camDist./term3; ...
        -term1./term2 -camDist./term2];

And outP now contains your normalized set of control points in the output image. Given an image of size s, we can create a set of input and output control points as follows:

scaledInP = [1 s(1); s(2) s(1); s(2) 1; 1 1];
scaledOutP = bsxfun(@times, outP+1, s([2 1])-1)./2+1;

And you can apply the transformation like so:

tform = fitgeotrans(scaledInP, scaledOutP, 'projective');
outputView = imref2d(s);
newImage = imwarp(oldImage, tform, 'OutputView', outputView);

The only issue you may come across is that a rotation of 90 degrees (i.e. looking end-on at the image plane) would create a set of collinear points that would cause fitgeotrans to error out. In such a case, you would technically just want a blank image, because you can't see a 2-D object when looking at it edge-on.

Here's some code illustrating the above transformations by animating a spinning image:

img = imread('peppers.png');
s = size(img);
outputView = imref2d(s);
scaledInP = [1 s(1); s(2) s(1); s(2) 1; 1 1];
viewAngle = 45;
camDist = sqrt(2)./tand(viewAngle./2);

for theta = linspace(0, 360, 360)
  term1 = camDist.*cosd(theta);
  term2 = camDist-sind(theta);
  term3 = camDist+sind(theta);
  outP = [-term1./term2  camDist./term2; ...
           term1./term3  camDist./term3; ...
           term1./term3 -camDist./term3; ...
          -term1./term2 -camDist./term2];
  scaledOutP = bsxfun(@times, outP+1, s([2 1])-1)./2+1;
  tform = fitgeotrans(scaledInP, scaledOutP, 'projective');
  spinImage = imwarp(img, tform, 'OutputView', outputView);
  if (theta == 0)
    hImage = image(spinImage);
    set(gca, 'Visible', 'off');
  else
    set(hImage, 'CData', spinImage);
  end
  drawnow;
end

And here's the animation:

这篇关于在MATLAB中围绕其中心旋转图像矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆