태그 보관물: numpy

numpy

cv2.Rodrigues 계산 중 Python 결과 변경 rmat=np.eye(4)

내가 달리면 :

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으로 3×1 1×3 또는 3×3이어야 하므로 아마도 전혀 버그가있을 수 있습니다. 실제로 rmat3 개의 요소가없는 1D 는 Python 래퍼에 의해 올바르게 거부됩니다. 내 의심은 2D ʻrmat`s가 파이썬 수준에서 제대로 확인되지 않았다는 것입니다. 그런 다음 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 기능의 버그입니다 …

해당 doc 을 읽으면 cv2.Rodrigues두 가지 다른 인터페이스가 있음을 알 수 있습니다.

C ++ 인터페이스를 모방 한 것으로, 회전 벡터 (및 선택적으로 jacobian)가 참조로 전달되고 함수에 의해 수정됩니다.

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

추가 조사 후 편집 :

함수는 예상대로 더 버그가 있습니다. 첫 번째 인터페이스를 사용할 때 매개 변수 dstjacobian수정되지 않습니다. 이는 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.

즉, 분명히 버그 보고서가 필요합니다 …


답변