Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image MATLAB中图像矩阵的中心旋转_Image_Matlab_Matrix_Affinetransform - Fatal编程技术网

Image MATLAB中图像矩阵的中心旋转

Image MATLAB中图像矩阵的中心旋转,image,matlab,matrix,affinetransform,Image,Matlab,Matrix,Affinetransform,假设我有一个2x2矩阵,其中填充了表示平面的值。现在我想以一种三维的方式,在“z方向”上旋转平面。要更好地理解,请参见下图: 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 = lins

假设我有一个2x2矩阵,其中填充了表示平面的值。现在我想以一种三维的方式,在“z方向”上旋转平面。要更好地理解,请参见下图:

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

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

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

%Make a box in the image
A(50:200-50,50:200-50) = 1;
现在,我可以通过旋转矩阵在二维房间中应用变换,如下所示:

R = affine2d([1 0 0; .5 1 0; 0 0 1])
tform = affine3d(R);
transformed = imwarp(A,tform);
然而,这将不会产生上述所需的输出,并且我不太确定如何创建二维仿射矩阵来创建这样的行为

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

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

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

您可以执行投影变换,该变换可以使用第一幅和第二幅图像中的角点位置进行估计

originalP='peppers.png';
original = imread(originalP);
imshow(original);
s = size(original);
matchedPoints1 = [1 1;1 s(1);s(2) s(1);s(2) 1];
matchedPoints2 = [1 1;1 s(1);s(2) s(1)-100;s(2) 100];
transformType = 'projective';

tform = fitgeotrans(matchedPoints1,matchedPoints2,'projective');

outputView = imref2d(size(original));
Ir = imwarp(original,tform,'OutputView',outputView);
figure; imshow(Ir);
这是上述代码的结果:

原始图像:

转换图像:

正确说明了如何应用所需的转换:与a一起使用,因此需要指定4个控制点(即输入和输出图像中的4对对应点)。然后可以使用应用此变换

那么,问题是如何选择这些点对来创建所需的转换,在本例中,转换就是创建一个新的转换。如下所示,透视投影考虑到观察位置(即“相机”)将具有定义圆锥视野的给定视角。通过获取此圆锥体内的所有三维点并将其投影到观察平面(位于摄影机目标处的平面,该平面垂直于连接摄影机及其目标的线)来渲染场景

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

camDist = sqrt(2)./tand(viewAngle./2);
scaledInP = [1 s(1); s(2) s(1); s(2) 1; 1 1];
scaledOutP = bsxfun(@times, outP+1, s([2 1])-1)./2+1;
现在我们可以使用它为转换生成一组控制点。我们首先将a应用于观察平面的角点,围绕y轴旋转一定量的θ。这会将它们旋转出平面,因此我们现在通过定义从摄影机到每个旋转的角点和角点的直线,将角点投影回查看平面。我将不给您数学推导(您可以通过上面链接中的公式自己实现它们),但在这种情况下,一切都简化为以下一组计算:

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];
outP
现在在输出图像中包含您的标准化控制点集。给定大小为
s
的图像,我们可以创建一组输入和输出控制点,如下所示:

camDist = sqrt(2)./tand(viewAngle./2);
scaledInP = [1 s(1); s(2) s(1); s(2) 1; 1 1];
scaledOutP = bsxfun(@times, outP+1, s([2 1])-1)./2+1;
您可以这样应用转换:

tform = fitgeotrans(scaledInP, scaledOutP, 'projective');
outputView = imref2d(s);
newImage = imwarp(oldImage, tform, 'OutputView', outputView);
您可能遇到的唯一问题是,旋转90度(即端视图像平面)将创建一组共线点,这将导致
fitgeotrans
出错。在这种情况下,从技术上讲,您只需要一张空白图像,因为您在边上看二维对象时看不到它

下面是一些通过设置旋转图像的动画来演示上述变换的代码:

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
下面是动画:


谢谢你的回答,这是正确的方向。是否可以直接指定角度?或者至少知道图像旋转了多少度?您可以使用三角法从图像左侧的角度计算黑色三角形的高度(即第6行中的
100
):
H=s(2)*tan(角弧度)
。但是我不知道如何从三维空间中的角度计算角度辐射度。当三维角度增加时,还需要收缩扭曲图形的宽度。可能有用。