cv2.Rodrigues 계산 중 Python 결과 변경


19

내가 달리면 :

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)줄이 주석 처리 되면 변경이 중단된다는 사실 이 시스템의 버그라고 생각합니다.


"e-310"은 0에 매우 가까운 부동 숫자입니다. 파이썬 부동 숫자 표현의 일반적인 문제처럼 보입니다. 이는 모든 메모리 할당에 따라 다를 수 있습니다.
Aryerez

이것은 정말 이상합니다 ... 나에게도 버그처럼 보입니다.
Julien

1
IMO의 가장 중요한 점은 tvec을 배열로 정의하지만 (int 또는 문자열이 아닌) 전혀 영향을 미치지 않는다는 것입니다. cv2.Rodrigues의 변조되지 않아야하지만, 인터페이스는 부작용에 의해 이러한 변조를 허용하는 것 같습니다 ...
Julien

혼란 스럽습니다. 루프를 풀면 두 개의 다른 변수 np.zeros(3)에 결과를 저장할 때 작동 합니다. 결과를 저장하지 않거나 동일한 변수를 두 번 사용하면 그렇지 않습니다. 아마도 더 많은 지식을 가진 사람이 이것에 대해 밝힐 수 있습니다.
나무 늘보

1
참고로, Windows의 Python3에서도 같은 내용을 볼 수 있습니다.
Julien

답변:


8

이것은에 의해 반환 된 것과 같이 초기화되지 않은 배열 일 가능성이 큽니다 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이어야 하므로 아마도 전혀 버그가있을 수 있습니다. 실제로 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.]]

의 경우 np.empty이 동작은 잘 알려져있다가 메모리를 필요하기 때문에 그들이 와서, 기존 값을 업데이트하지 않고, 바이트. 그러나이 cv2.Rodrigues함수는 엄격한 계산 후에 의미있는 값을 반환해야합니다. 또한 OP에 제시된 이상한 값은 모두 0에 매우 가깝기 때문에 쓰레기로 간주 될 수 없습니다.
sciroccorics

1
@sciroccorics 당신은 내 두 번째 발췌 문장이 꽤 매력적이라는 것에 동의하지 않습니까?
Paul Panzer

입력 크기를 확인하기 위해 PR 을 제출했습니다 .
Catree

3

확실히, 그것은 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.

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


다른 대답 은 맞습니다. 문제는에서 발생 np.eye(4)합니다. 이 방법에는 (3x1 또는 1x3) 회전 벡터 또는 (3x3) 회전 행렬이 필요합니다. 여기 np.eye (4)를 사용하면 함수가 약간의 크기로 dst를 만듭니다. 그러나 입력 모양이 잘못 되었기 때문에이 방법은 아무 것도 수행하지 않고 통합 된 상태로 둡니다. 또한 구식 OpenCV 버전을 가리키고 있습니다. 마스터 버전을 사용하거나 특정 버전을 가리키는 것이 좋습니다 (docs.opencv.org 참조) .
Catree
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.