编程语言
首页 > 编程语言> > Python中的仿射3D转换

Python中的仿射3D转换

作者:互联网

我在Autodesk Maya中使用Python编写函数(使用PyMel for Maya)

我有3个3D点; p0,p1,p2.

然后他们进行了严格的转换,因此在转换(仿射转换)之后,我有了新的职位. q0,q1,q2

在转换之前,我还有第四点. p3.我想在相同的转换后计算它的位置; q4.

因此,我需要计算转换矩阵,然后将其应用于p4.我也不知道该怎么办.列表=对象数组

import pymel.core as pm
import pymel.core.datatypes as dt

p0 = dt.Vector(pm.getAttr(list[0]+".tx"), pm.getAttr(list[0]+".ty"), pm.getAttr(list[0]+".tz"))
p1 = dt.Vector(pm.getAttr(list[1]+".tx"), pm.getAttr(list[1]+".ty"), pm.getAttr(list[1]+".tz"))
p2 = dt.Vector(pm.getAttr(list[2]+".tx"), pm.getAttr(list[2]+".ty"), pm.getAttr(list[2]+".tz")
p3 = dt.Vector(pm.getAttr(list[3]+".tx"), pm.getAttr(list[3]+".ty"), pm.getAttr(list[3]+".tz"))

从Maya场景中的动画对象读取3D点.所以在另一帧,
我运行此代码来获取

q0 = dt.Vector(pm.getAttr(list[0]+".tx"), pm.getAttr(list[0]+".ty"), pm.getAttr(list[0]+".tz"))
q1 = dt.Vector(pm.getAttr(list[1]+".tx"), pm.getAttr(list[1]+".ty"), pm.getAttr(list[1]+".tz"))
q2 = dt.Vector(pm.getAttr(list[2]+".tx"), pm.getAttr(list[2]+".ty"), pm.getAttr(list[2]+".tz"))
#q3 = TransformationMatrix between (p0,p1,p2) and (q0,q1,q2), applied to p3

我试图用向量进行计算,但由于除以零而导致错误…
因此,我认为转换矩阵应该可以毫无问题地解决它.

我的截止日期不远了,我真的需要帮助解决这个问题!
请帮忙!

编辑:
how to perform coordinates affine transformation using python?

我需要此函数“ solve_affine”,但每个集合应只取3分而不是4分.而且我不能使用numpy …

解决方法:

这是使用numpy和scipy的解决方案. scipy主要用于生成随机旋转,但scipy.linalg.norm易于编写代码. numpy使用的主要内容是叉积和矩阵乘法,它们也很容易自己编写.

基本思想是:给定三个非共线点x1,x2,x3,可以找到向量(轴)v1,v2,v3的正交三倍,其中v1沿平面x2-x1,v2的方向跨度为(x2-x1)和(x3-x1),而v3完成三元组.

y1,y2,y3点相对于x1,x2,x3旋转和平移.从y1,y2,y3生成的轴w1,w2,w3从v1,v2,v3旋转(即无平移).这两组三元组彼此正交,因此很容易从中找到旋转:R = W * transpose(V)

一旦有了旋转,找到平移就很简单了:y1 = R * x t,所以t = y1-R * x.使用最小二乘解算器并结合所有三个点以获得t的估计可能更好.

import numpy
import scipy.linalg


def rand_rot():
    """Return a random rotation

    Return a random orthogonal matrix with determinant 1"""
    q, _ = scipy.linalg.qr(numpy.random.randn(3, 3))
    if scipy.linalg.det(q) < 0:
        # does this ever happen?
        print "got a negative det"
        q[:, 0] = -q[:, 0]
    return q


def rand_noncollinear():
    """Return 3 random non-collinear vectors"""
    while True:
        b = numpy.random.randn(3, 3)
        sigma = scipy.linalg.svdvals(b)
        if sigma[2]/sigma[0] > 0.1:
            # "very" non-collinear
            break
        # "nearly" collinear; try again

    return b[:, 0], b[:, 1], b[:, 2]


def normalize(a):
    """Return argument normalized"""
    return a/scipy.linalg.norm(a)


def colstack(a1, a2, a3):
    """Stack three vectors as columns"""
    return numpy.hstack((a1[:, numpy.newaxis],
                         a2[:, numpy.newaxis],
                         a3[:, numpy.newaxis]))


def get_axes(a1, a2, a3):
    """Generate orthogonal axes from three non-collinear points"""
    # I tried to do this with QR, but something didn't work
    b1 = normalize(a2-a1)
    b2 = normalize(a3-a1)
    b3 = normalize(numpy.cross(b1, b2))
    b4 = normalize(numpy.cross(b3, b1))
    return b1, b4, b3

# random rotation and translation
r = rand_rot()
t = numpy.random.randn(3)

# three non-collinear points
x1, x2, x3 = rand_noncollinear()
# some other point
x4 = numpy.random.randn(3)

# the images of the above in the transformation.
# y4 is for checking only -- won't be used to estimate r or t
y1, y2, y3, y4 = [numpy.dot(r, x) + t
                  for x in x1, x2, x3, x4]


v1, v2, v3 = get_axes(x1, x2, x3)
w1, w2, w3 = get_axes(y1, y2, y3)

V = colstack(v1, v2, v3)
W = colstack(w1, w2, w3)

# W = R V, so R = W * inverse(V); but V orthogonal, so inverse(V) is
# transpose(V):
rfound = numpy.dot(W, V.T)

# y1 = R x1 + t, so...
tfound = y1-numpy.dot(r, x1)

# get error on images of x2 and x3, just in case

y2err = scipy.linalg.norm(numpy.dot(rfound, x2) + tfound - y2)
y3err = scipy.linalg.norm(numpy.dot(rfound, x3) + tfound - y3)

# and check error image of x4 -- getting an estimate of y4 is the
# point of all of this
y4err = scipy.linalg.norm(numpy.dot(rfound, x4) + tfound - y4)

print "y2 error: ", y2err
print "y3 error: ", y3err
print "y4 error: ", y4err

标签:affinetransform,matrix,transformation,pymel,python
来源: https://codeday.me/bug/20191121/2054370.html