Python 结果在 cv2.Rodrigues 计算期间发生变化
Python result changes during cv2.Rodrigues computation
如果我运行:
import numpy as np
import cv2
def changes():
rmat=np.eye(4)
tvec=np.zeros(3)
(rvec, jacobian)=cv2.Rodrigues(rmat)
print rvec
for i in range(2):
changes()
我得到:
[[6.92798859e-310]
[2.19380404e-316]
[1.58101007e-322]]
[[0.]
[0.]
[0.]]
因此 changes()
的结果发生了变化。
我不明白为什么会这样,而且如果 tvec=np.zeros(3)
行被注释掉它就会停止更改,这让我觉得这是系统中的错误。
这很可能是一个未初始化的数组,例如 np.empty
返回的数组。这与内存回收一起可以导致您所看到的那种效果。一个最小的例子是:
for a in range(5):
y = np.empty(3,int)
x = (np.arange(3)+a)**3
print(x,y)
del x
# [0 1 8] [94838139529536 0 0]
# [ 1 8 27] [0 1 8]
# [ 8 27 64] [ 1 8 27]
# [ 27 64 125] [ 8 27 64]
# [ 64 125 216] [ 27 64 125]
观察第一次迭代 y
是如何包含垃圾的,并且在每次后续迭代中它包含前一个 x
的值,因为它被分配了刚刚释放的内存。
我们可以很容易地检查出在原来的例子中弹出的也是前面的tvec
:
def changes():
rmat=np.eye(4)
tvec=np.array([4,0.0,2.5])
(rvec, jacobian)=cv2.Rodrigues(rmat)
print(rvec)
for i in range(3):
changes()
# [[4.6609787e-310]
# [0.0000000e+000]
# [0.0000000e+000]]
# [[4. ]
# [0. ]
# [2.5]]
# [[4. ]
# [0. ]
# [2.5]]
我们可以进一步推测是 rmat
的特殊选择触发了错误。
eye(4)
被完全接受可能是一个错误,因为正式地,rmat
应该是 3x1 1x3 或 3x3。实际上,没有 3 个元素的一维 rmat
会被 Python 包装器正确拒绝。我怀疑 2D rmat 没有在 Python 级别正确检查。然后 C 代码检测到错误的形状,除了返回 Python 代码不检查的错误代码外什么都不做。
确实使用 rmat=eye(3)
效果消失了:
def changes():
rmat=np.eye(3)
tvec=np.array([4,0.0,2.5])
(rvec, jacobian)=cv2.Rodrigues(rmat)
print(rvec)
for a in range(3):
changes()
# [[0.]
# [0.]
# [0.]]
# [[0.]
# [0.]
# [0.]]
# [[0.]
# [0.]
# [0.]]
毫无疑问,这是 Rodrigues 函数中的一个错误...
如果您阅读 corresponding doc,您可能会看到 cv2.Rodrigues
有 2 个不同的界面:
模仿 C++ 接口的一个,其中旋转向量(和可选的雅可比矩阵)通过引用传递并由函数修改
cv2.Rodrigues(src, dst[, jacobian]) --> None
还有一个(更像 Pythonic),其中旋转向量和雅可比矩阵作为元组返回
cv2.Rodrigues(src) --> dst, jacobian
如果使用第一个界面,pb 消失...
import numpy as np
import cv2
def changes():
rmat=np.eye(4)
tvec=np.zeros(3)
#(rvec, jacobian)=cv2.Rodrigues(rmat)
cv2.Rodrigues(rmat, tvec)
print(tvec)
for i in range(2):
changes()
结果:
[0. 0. 0.]
[0. 0. 0.]
进一步调查后编辑:
这个函数比预期的还要多bug:使用第一个接口时,参数dst
和jacobian
没有被修改,这与docstring完全矛盾:
>>> help(cv2.Rodrigues)
Help on built-in function Rodrigues:
Rodrigues(...)
Rodrigues(src[, dst[, jacobian]]) -> dst, jacobian
. @brief Converts a rotation matrix to a rotation vector or vice versa.
.
. @param src Input rotation vector (3x1 or 1x3) or rotation matrix (3x3).
. @param dst Output rotation matrix (3x3) or rotation vector (3x1 or 1x3), respectively.
. @param jacobian Optional output Jacobian matrix, 3x9 or 9x3, which is a matrix of partial
. derivatives of the output array components with respect to the input array components.
换句话说,这显然需要错误报告...
如果我运行:
import numpy as np
import cv2
def changes():
rmat=np.eye(4)
tvec=np.zeros(3)
(rvec, jacobian)=cv2.Rodrigues(rmat)
print rvec
for i in range(2):
changes()
我得到:
[[6.92798859e-310]
[2.19380404e-316]
[1.58101007e-322]]
[[0.]
[0.]
[0.]]
因此 changes()
的结果发生了变化。
我不明白为什么会这样,而且如果 tvec=np.zeros(3)
行被注释掉它就会停止更改,这让我觉得这是系统中的错误。
这很可能是一个未初始化的数组,例如 np.empty
返回的数组。这与内存回收一起可以导致您所看到的那种效果。一个最小的例子是:
for a in range(5):
y = np.empty(3,int)
x = (np.arange(3)+a)**3
print(x,y)
del x
# [0 1 8] [94838139529536 0 0]
# [ 1 8 27] [0 1 8]
# [ 8 27 64] [ 1 8 27]
# [ 27 64 125] [ 8 27 64]
# [ 64 125 216] [ 27 64 125]
观察第一次迭代 y
是如何包含垃圾的,并且在每次后续迭代中它包含前一个 x
的值,因为它被分配了刚刚释放的内存。
我们可以很容易地检查出在原来的例子中弹出的也是前面的tvec
:
def changes():
rmat=np.eye(4)
tvec=np.array([4,0.0,2.5])
(rvec, jacobian)=cv2.Rodrigues(rmat)
print(rvec)
for i in range(3):
changes()
# [[4.6609787e-310]
# [0.0000000e+000]
# [0.0000000e+000]]
# [[4. ]
# [0. ]
# [2.5]]
# [[4. ]
# [0. ]
# [2.5]]
我们可以进一步推测是 rmat
的特殊选择触发了错误。
eye(4)
被完全接受可能是一个错误,因为正式地,rmat
应该是 3x1 1x3 或 3x3。实际上,没有 3 个元素的一维 rmat
会被 Python 包装器正确拒绝。我怀疑 2D rmat 没有在 Python 级别正确检查。然后 C 代码检测到错误的形状,除了返回 Python 代码不检查的错误代码外什么都不做。
确实使用 rmat=eye(3)
效果消失了:
def changes():
rmat=np.eye(3)
tvec=np.array([4,0.0,2.5])
(rvec, jacobian)=cv2.Rodrigues(rmat)
print(rvec)
for a in range(3):
changes()
# [[0.]
# [0.]
# [0.]]
# [[0.]
# [0.]
# [0.]]
# [[0.]
# [0.]
# [0.]]
毫无疑问,这是 Rodrigues 函数中的一个错误...
如果您阅读 corresponding doc,您可能会看到 cv2.Rodrigues
有 2 个不同的界面:
模仿 C++ 接口的一个,其中旋转向量(和可选的雅可比矩阵)通过引用传递并由函数修改
cv2.Rodrigues(src, dst[, jacobian]) --> None
还有一个(更像 Pythonic),其中旋转向量和雅可比矩阵作为元组返回
cv2.Rodrigues(src) --> dst, jacobian
如果使用第一个界面,pb 消失...
import numpy as np
import cv2
def changes():
rmat=np.eye(4)
tvec=np.zeros(3)
#(rvec, jacobian)=cv2.Rodrigues(rmat)
cv2.Rodrigues(rmat, tvec)
print(tvec)
for i in range(2):
changes()
结果:
[0. 0. 0.]
[0. 0. 0.]
进一步调查后编辑:
这个函数比预期的还要多bug:使用第一个接口时,参数dst
和jacobian
没有被修改,这与docstring完全矛盾:
>>> help(cv2.Rodrigues)
Help on built-in function Rodrigues:
Rodrigues(...)
Rodrigues(src[, dst[, jacobian]]) -> dst, jacobian
. @brief Converts a rotation matrix to a rotation vector or vice versa.
.
. @param src Input rotation vector (3x1 or 1x3) or rotation matrix (3x3).
. @param dst Output rotation matrix (3x3) or rotation vector (3x1 or 1x3), respectively.
. @param jacobian Optional output Jacobian matrix, 3x9 or 9x3, which is a matrix of partial
. derivatives of the output array components with respect to the input array components.
换句话说,这显然需要错误报告...