在python中的3D图像旋转

Rav*_*310 10 python 3d opencv computer-vision image-rotation

我有以下图像I1.我没有抓住它.我是从谷歌下载的

在此输入图像描述

我将已知的单应性h应用于I1以获得以下图像I2.

在此输入图像描述

我想假设一台相机拍摄了I2以上的照片.我找到了这个"相机"的相机矩阵.让这个相机矩阵k.现在,我想围绕相机轴旋转此图像I2.根据该问题中接受的答案中的解释,我需要设置旋转矩阵R然后k*R*inv(k)*h对图像I1 执行以获得所需的旋转图像I3.

当我尝试设置此旋转矩阵R时,我遇到了问题.我已经使用此方法设置矩阵R.

为了测试我的代码,我最初试图围绕z轴旋转图像10度,但我得不到正确的输出.

我的部分Python代码:

theta_in_degrees = 10
theta_in_radians = theta_in_degrees*math.pi/180
ux=0.0 
uy=0.0 
uz=1.0 
vector_normalize_factor = math.sqrt(ux*ux+uy*uy+uz*uz)
ux=ux/vector_normalize_factor
uy=uy/vector_normalize_factor
uz=uz/vector_normalize_factor
print "ux*ux+uy*uy+uz*uz = ", ux*ux+uy*uy+uz*uz 
rotation_matrix = np.zeros([3,3])
c1 = math.cos(theta_in_radians)
c2 = 1-c1
s1 = math.sin(theta_in_radians)
rotation_matrix[0][0] = c1+ux*ux*c2
rotation_matrix[0][1] = ux*uy*c2-uz*s1
rotation_matrix[0][2] = ux*uz*c2+uy*s1
rotation_matrix[1][0] = uy*ux*c2+uz*s1
rotation_matrix[1][1] = c1+uy*uy*c2
rotation_matrix[1][2] = uy*uz*c2-ux*s1
rotation_matrix[2][0] = uz*ux*c2-uy*s1
rotation_matrix[2][1] = uz*uy*c2+ux*s1
rotation_matrix[2][2] = c1+uz*uz*c2
print "rotation_matrix = ", rotation_matrix
R = rotation_matrix
#Calculate homography H1 between reference top view and rotated frame
k_inv = np.linalg.inv(k)
Hi = k.dot(R)
Hii = k_inv.dot(h)
H1 = Hi.dot(Hii)
print "H1 = ", H1
im_out = cv2.warpPerspective(im_src, H1, (im_dst.shape[1],im_dst.shape[0]))
Run Code Online (Sandbox Code Playgroud)

在这里,img_src是I1的来源.

我在尝试上面的代码时得到的结果是一个黑色图像,图像的任何部分都不可见.但是,当我将值更改为theta_in_degrees以下值时,这些是我的输出:

0.00003

在此输入图像描述

0.00006

在此输入图像描述

0.00009

在此输入图像描述

为什么旋转仅适用于如此小的值theta_in_degrees?此外,图像中可见的旋转实际上并非围绕z轴发生.为什么图像不绕z轴旋转?我哪里出错了,我该如何解决这些问题?

h矩阵:

[[  1.71025842e+00  -7.51761942e-01   1.02803446e+02]
 [ -2.98552735e-16   1.39232576e-01   1.62792482e+02]
 [ -1.13518150e-18  -2.27094753e-03   1.00000000e+00]]
Run Code Online (Sandbox Code Playgroud)

k矩阵:

[[  1.41009391e+09   0.00000000e+00   5.14000000e+02]
 [  0.00000000e+00   1.78412347e+02   1.17000000e+02]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00]]
Run Code Online (Sandbox Code Playgroud)

编辑:

在结合Toby Collins的建议后,我将左上角的值设置k为相同k[1][1].当我现在围绕z轴执行旋转时,我获得了theta_in_degrees从0到360的所有值的正确旋转图像.但是,当我尝试通过更改ux,uy和uz来绕y轴旋转图像时上面的代码如下,我得到了荒谬的旋转结果:

ux=0.0 
uy=1.0 
uz=0.0 
Run Code Online (Sandbox Code Playgroud)

有关不同值的一些样本theta_in_degrees和围绕y轴旋转的相应结果如下所示:

-10

在此输入图像描述

-40

在此输入图像描述

-90

在此输入图像描述

-110

在此输入图像描述

我哪里还出错?另外,为什么旋转图像中连续黄色条纹的长度和宽度会出现如此大的下降?为什么图像的一部分环绕(例如,旋转结果为-90和-110度)?

我的问题的第二部分是:我的旋转轴的矢量方程是(320, 0, -10)+t(0, 1, 0).为了使用此方法,以计算旋转矩阵,我需要定义ux,uyuz旋转,使得轴的ux^2+uy^2+uz^2=1.如果需要围绕其中一个坐标轴进行旋转(这是我目前正在进行测试),这将是直截了当的.但我怎么得到的这些值ux,uy并且uz如果t我的旋转轴的矢量方程变量?我也对有关找到合适的旋转矩阵R的任何其他方法的建议持开放态度,使得旋转发生在我提到的轴周围(例如,x度).

Tob*_*ins 6

您遇到的困难是您的单应矩阵h与使用合理的透视相机获得的投影不完全对应.我认为有一种更简单的方法.

从根本上说,您需要非常清楚自己的技术目标,并将其与解决问题的方法区分开来.无论何时解决任何视力问题,都要始终这样做.

技术目标

所以让我们清楚一下技术目标.您有一个自上而下的平面图像(也称为整流视图).通常,您可以将此曲面称为在z = 0平面上定义的模型.您想要渲染此模型.具体来说,你想做以下事情;

  1. 创建虚拟透视摄像机,从特定视点查看模型.我们定义该模型对照相机刚性通过变换- [R 1, 1,用本征矩阵ķ.
  2. 通过围绕其投影中心旋转摄像机来移动摄像机.让我们用R 2 表示这种旋转.
  3. 使用2中的视图渲染模型.我们将此图像称为I2

为简单起见,我将使用T(R,t)来表示一些旋转R和平移t的4x4齐次刚性变换.因此,阶段3 的模型到相机变换由T = T(R2,(0,0,0))×T(R1,t1)给出.

渲染选项

创建I2有两种好方法

  1. 使用 OpenGL或Ogre等渲染引擎.这样做的优点是可以很容易地制作用于改变摄像机视点的GUI,并且可以添加其他复杂的渲染效果.

  2. 确定模型到图像的单应矩阵并使用OpenCV进行渲染warpPerspective.这样做的好处是它可以在几行中完成,而不会破坏渲染软件.缺点是如果单应性在渲染中有一个消失点(正如你所观察到的那样),你可以得到一些奇怪的效果.稍后更多关于这一点.

模型到图像单应性的定义

为了使用OpenCV方法,我们将模型到图像的单应性定义为H 2.这可以根据相机参数来定义.考虑均匀坐标中模型平面上的点p =(x,y,1).它在齐次坐标中的I2中的位置qq = KM p给出,其中M是.由M =(T00,T01,T03; T10,T11,T13; T20,T21,T23)给出的3×3矩阵.使用透视摄像机模型可以直接推导出这种情况.因此,我们现在有H 2 = KM.

实例化单应矩阵

现在我们必须实例化单应性,不像你提出的方法,我会使用特定的相机配置,通过指定K,R 1,t 1,R 2 来定义它.选择取决于你!要简化K的定义,您可以使用带有一个自由参数(焦距)的简单形式,并将主要点设置为图像中心.对于典型的相机,f范围在图像宽度的0.5到2倍之间,但这取决于您.然后,您需要根据视角所需的视角/距离设置R 1和t 1.

这与您当前的方法有何不同?

我想强调的是,这与我之前给出的任何答案都不矛盾.这只是一种可能更容易管理的不同方法.基本上,在这里我建议直接使用相机参数(您根据需要设置)来定义您的单应性.这可以保证您使用合理的内在矩阵(因为您自己设置).这与您首先创建单应性然后想要找到匹配的相机参数(可能与否在物理上是合理的)的方法不同.