我有以下图片I1。我没有抓住它。我是从Google下载的
我将已知的单应性h应用于I1以获得以下图像I2。
我想假设一台相机拍摄了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
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]]
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
-40
-90
-110
我还在哪里错?另外,为什么旋转图像中连续黄色条纹的长度和宽度会出现如此大的下降?为什么图像的一部分环绕(例如,旋转结果为-90和-110度)?
我的问题的第二部分是:我的旋转轴的矢量方程是(320, 0, -10)+t(0, 1, 0)
。为了使用来计算旋转矩阵,我需要定义旋转轴的ux
,uy
和uz
,以便ux^2+uy^2+uz^2=1
。如果需要围绕其中一个坐标轴进行旋转(这是我目前正在进行测试),这将是直截了当的。但是,如果我的旋转轴的矢量方程中的ux
是可变的,我如何获得uy
,uz
和t
的这些值?我也对任何其他寻找合适的旋转矩阵R的方法持开放态度,以便旋转发生在我提到的轴周围(例如,x度)。
答案 0 :(得分:5)
您遇到的困难是您的单应矩阵 h 与使用合理透视相机获得的投影不完全对应。我认为有一种更简单的方法。
从根本上说,您需要非常清楚自己的技术目标,并将其与解决问题的方法区分开来。每当您解决任何视力问题时,请务必执行此操作。
因此,让我们明确技术目标。您有一个自上而下的平面图像(也称为整流视图)。通常,您将此平面称为在平面z = 0上定义的模型。您想要渲染此模型。具体来说,您想要执行以下操作;
为简单起见,我将使用T( R , t )来表示4x4齐次刚性变换的某些旋转 R 和翻译 t 。因此,第3阶段的模型到相机变换由 T = T( R2 ,(0,0,0))x给出T( R1 , t 1)。
创建 I2
有两种好方法使用渲染引擎,例如OpenGL或Ogre。这样做的好处是可以很容易地制作用于更改摄像机视点的GUI,并且可以添加其他复杂的渲染效果。
确定模型到图像的单应矩阵,并使用warpPerspective
使用OpenCV进行渲染。这样做的好处是它可以在几行中完成,而不会破坏渲染软件。缺点是如果单应性在渲染中有一个消失点(正如你所观察到的那样),你可以得到一些奇怪的效果。关于这一点的更多内容。
要使用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,具体取决于您对视点所需的视角/距离。
我想强调的是,这与我之前给出的任何答案都不矛盾。这只是一种可能更容易管理的不同方法。基本上,在这里我建议直接使用相机参数(您根据需要设置)来定义您的单应性。这可以保证您使用合理的内在矩阵(因为您自己设置)。这与您首先创建单应性然后想要找到匹配的相机参数(可能与否在物理上是合理的)的方法不同。