图像上的 3D 旋转
我正在尝试获取一些代码来对图像执行透视变换(在本例中为 3d 旋转)。
import os.path
import numpy as np
import cv
def rotation(angle, axis):
return np.eye(3) + np.sin(angle) * skew(axis) \
+ (1 - np.cos(angle)) * skew(axis).dot(skew(axis))
def skew(vec):
return np.array([[0, -vec[2], vec[1]],
[vec[2], 0, -vec[0]],
[-vec[1], vec[0], 0]])
def rotate_image(imgname_in, angle, axis, imgname_out=None):
if imgname_out is None:
base, ext = os.path.splitext(imgname_in)
imgname_out = base + '-out' + ext
img_in = cv.LoadImage(imgname_in)
img_size = cv.GetSize(img_in)
img_out = cv.CreateImage(img_size, img_in.depth, img_in.nChannels)
transform = rotation(angle, axis)
cv.WarpPerspective(img_in, img_out, cv.fromarray(transform))
cv.SaveImage(imgname_out, img_out)
当我绕 z 轴旋转时,一切都按预期工作,但绕 x 或 y 轴旋转似乎完全不正常。在开始获得看起来完全合理的结果之前,我需要旋转小至 pi/200 的角度。知道可能出什么问题吗?
I'm trying to get some code that will perform a perspective transformation (in this case a 3d rotation) on an image.
import os.path
import numpy as np
import cv
def rotation(angle, axis):
return np.eye(3) + np.sin(angle) * skew(axis) \
+ (1 - np.cos(angle)) * skew(axis).dot(skew(axis))
def skew(vec):
return np.array([[0, -vec[2], vec[1]],
[vec[2], 0, -vec[0]],
[-vec[1], vec[0], 0]])
def rotate_image(imgname_in, angle, axis, imgname_out=None):
if imgname_out is None:
base, ext = os.path.splitext(imgname_in)
imgname_out = base + '-out' + ext
img_in = cv.LoadImage(imgname_in)
img_size = cv.GetSize(img_in)
img_out = cv.CreateImage(img_size, img_in.depth, img_in.nChannels)
transform = rotation(angle, axis)
cv.WarpPerspective(img_in, img_out, cv.fromarray(transform))
cv.SaveImage(imgname_out, img_out)
When I rotate about the z-axis, everything works as expected, but rotating around the x or y axis seems completely off. I need to rotate by angles as small as pi/200 before I start getting results that seem at all reasonable. Any idea what could be wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,构建旋转矩阵,其形式
为应用此坐标变换可以围绕原点进行旋转。
相反,如果您想绕图像中心旋转,则必须首先移动图像中心
到原点,然后应用旋转,然后将所有内容移回原点。您可以使用
平移矩阵:
平移、旋转和逆平移的变换矩阵变为:
我必须考虑一下如何将倾斜矩阵与 3D 变换联系起来。我预计最简单的方法是设置 4D 变换矩阵,然后将其投影回 2D 齐次坐标。但目前,倾斜矩阵的一般形式:
x_skew 和 y_skew 值通常很小(1e-3 或更小)。
这是代码:
输出:
First, build the rotation matrix, of the form
Applying this coordinate transform gives you a rotation around the origin.
If, instead, you want to rotate around the image center, you have to first shift the image center
to the origin, then apply the rotation, and then shift everything back. You can do so using a
translation matrix:
The transformation matrix for translation, rotation, and inverse translation then becomes:
I'll have to think a bit about how to relate the skew matrix to the 3D transformation. I expect the easiest route is to set up a 4D transformation matrix, and then to project that back to 2D homogeneous coordinates. But for now, the general form of the skew matrix:
The
x_skew
andy_skew
values are typically tiny (1e-3 or less).Here's the code:
And the output:
我不明白你构建旋转矩阵的方式。对我来说这似乎相当复杂。通常,它会通过构造一个零矩阵,将
1
放在不需要的轴上,以及常见的sin
、cos
、- 来构建cos
、sin
转换为两个使用的维度。然后将所有这些相乘。你从哪里得到的
np.eye(3) + np.sin(angle) * skew(axis) + (1 - np.cos(angle)) * skew(axis).dot(skew(axis))
构造自?尝试从基本构建块构建投影矩阵。构建旋转矩阵相当容易,“旋转矩阵点倾斜矩阵”应该可以工作。
不过,您可能需要注意旋转中心。您的图像可能放置在 z 轴上的虚拟位置 1 处,因此通过在 x 或 y 上旋转,它会移动一点。
因此,您需要使用平移,使 z 变为 0,然后旋转,然后平移回来。 (仿射坐标中的平移矩阵也非常简单。请参阅维基百科:https://en.wikipedia.org/维基/Transformation_matrix )
I do not get the way you build your rotation matrix. It seems rather complicated to me. Usually, it would be built by constructing a zero matrix, putting
1
on unneeded axes, and the commonsin
,cos
,-cos
,sin
into the two used dimensions. Then multiplying all these together.Where did you get that
np.eye(3) + np.sin(angle) * skew(axis) + (1 - np.cos(angle)) * skew(axis).dot(skew(axis))
construct from?Try building the projection matrix from basic building blocks. Constructing a rotation matrix is fairly easy, and "rotationmatrix dot skewmatrix" should work.
You might need to pay attention to the rotation center though. Your image probably is placed at a virtual position of 1 on the z axis, so by rotating on x or y, it moves around a bit.
So you'd need to use a translation so z becomes 0, then rotate, then translate back. (Translation matrixes in affine coordinates are pretty simple, too. See wikipedia: https://en.wikipedia.org/wiki/Transformation_matrix )