Pythonの結果はcv2.Rodriguesの計算中に変化します


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に非常に近い浮動小数点数です。これは、Python浮動小数点数表現の一般的な問題のようであり、メモリの割り当てごとに異なる場合があります。
Aryerez

これは非常に奇妙です...私にとってもバグのようです。
ジュリアン

1
IMOの主なものは、tvecを配列として(ただし、intまたはstringとしてではなく)定義すると、まったく効果があるということです...そして、一度実行すると、後戻りできません...私の推測では、tvecは内部状態です。 cv2.Rodriguesの改ざんされるべきではありませんが、インターフェイスは副作用によってそのような改ざんを許可しているようです...
Julien

これは紛らわしいです。ループを展開するとnp.zeros(3)2つの異なる変数に結果を保存すると機能します。結果を保存しないか、同じ変数を2回使用しない場合は、保存されません。たぶんもっとおかしな知識を持っている人はこれにいくつかの光を当てることができます。
ナマケモノ

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

以下の場合np.empty、この動作はよく知られている、それはメモリがかかるため、彼らが来るとして、既存の値を更新せずに、バイト。しかし、cv2.Rodrigues関数は厳密な計算の後に、いくつかの意味のある値を返すことになっています。さらに、OPに表示される奇妙な値は、それらがすべてゼロに非常に近いため、ガベージとはほとんど見なされません。
sciroccorics

1
@sciroccorics私の2番目のスニペットが非常に説得力があることに同意しませんか?
Paul Panzer、

入力サイズを確認するためのPRを提出しました。
Catree

3

間違いなく、それはロドリゲス関数のバグです...

対応するdocを読むと、cv2.Rodrigues2つの異なるインターフェースがあることがわかります。

C ++インターフェイスを模倣したもので、回転ベクトル(およびオプションでヤコビアン)が参照によって渡され、関数によって変更されます。

cv2.Rodrigues(src, dst[, jacobian]) --> None

1つ(より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ドキュメント文字列で合計contracdictionにある、変更されません。

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