python中的3D图像旋转

时间:2018-01-16 13:57:50

标签: python opencv 3d computer-vision image-rotation

我有以下图片I1。我没有抓住它。我是从Google下载的

enter image description here

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

enter image description here

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

当我尝试设置此旋转矩阵R时,我遇到了问题。我使用this question来设置矩阵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]))

此处,img_src是I1的来源。

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

0.00003

this method

0.00006

enter image description here

0.00009

enter image description here

为什么轮换仅适用于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]]

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]]

修改

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

ux=0.0 
uy=1.0 
uz=0.0 

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

-10

enter image description here

-40

enter image description here

-90

enter image description here

-110

enter image description here

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

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

1 个答案:

答案 0 :(得分:5)

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

从根本上说,您需要非常清楚自己的技术目标,并将其与解决问题的方法区分开来。每当您解决任何视力问题时,请务必执行此操作。

技术目标

因此,让我们明确技术目标。您有一个自上而下的平面图像(也称为整流视图)。通常,您将此平面称为在平面z = 0上定义的模型。您想要渲染此模型。具体来说,您想要执行以下操作;

  1. 创建一个虚拟透视摄像头,从特定视点查看模型。我们通过 R 1, t 1来定义此模型到相机的刚性变换,并使用内部矩阵 K
  2. 通过围绕投影中心旋转相机来移动相机。我们用 R 2来表示这种旋转。
  3. 使用2中的视图渲染模型。我们将此图像称为 I2
  4. 为简单起见,我将使用T( R t )来表示4x4齐次刚性变换的某些旋转 R 和翻译 t 。因此,第3阶段的模型到相机变换由 T = T( R2 ,(0,0,0))x给出T( R1 t 1)。

    渲染选项

    创建 I2

    有两种好方法
    1. 使用渲染引擎,例如OpenGL或Ogre。这样做的好处是可以很容易地制作用于更改摄像机视点的GUI,并且可以添加其他复杂的渲染效果。

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

    3. 模型到图像单应性的定义

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

      实例化单应矩阵

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

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

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