Изменения результата Python во время вычисления cv2.Rodrigues - PullRequest
19 голосов
/ 21 ноября 2019

Если я бегу:

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) закомментирована, заставляет меня чувствовать, что это ошибка в системе.

Ответы [ 2 ]

8 голосов
/ 18 декабря 2019

Скорее всего, это неинициализированный массив, например, возвращаемый 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. Действительно, 1D rmat, у которого нет 3 элементов, корректно отклоняется оболочкой Python. Я подозреваю, что 2D-карты не проверены должным образом на уровне 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.]]
3 голосов
/ 18 декабря 2019

Определенно, это ошибка в функции Родригеса ...

Если вы прочитаете соответствующий документ , вы можете увидеть, что 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.]

РЕДАКТИРОВАТЬ после дальнейшего исследования:

Функция еще более глючная, как и ожидалось: при использовании первого интерфейса параметры dst и jacobian не изменяются, что полностью противоречит строке документации:

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

Другими словами, это явно требует сообщения об ошибке ...

...