Cv2 के दौरान पाइथन परिणाम बदलता है। शरीर की गणना


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)लाइन पर टिप्पणी की जाती है, तो मुझे लगता है कि यह सिस्टम में एक बग है।


"ई -310" फ्लोटिंग संख्याओं के बहुत करीब हैं। यह अजगर फ्लोटिंग संख्या प्रतिनिधित्व के साथ सामान्य मुद्दे की तरह दिखता है, जो मेमोरी के हर आवंटन पर भिन्न हो सकता है।
आर्यसेर

यह गंभीर रूप से अजीब है ... मेरे लिए एक बग की तरह लग रहा है।
जुलिएन

1
IMO की मुख्य बात यह है कि tvec को एक सरणी के रूप में परिभाषित करना (लेकिन इंट या स्ट्रिंग के रूप में नहीं) का प्रभाव बिल्कुल होता है ... और एक बार जब आप इसे कर लेते हैं, तो कोई पीछे नहीं हटता ... मेरा अनुमान है कि एक आंतरिक स्थिति है cv2। शरीर के साथ छेड़छाड़ नहीं की जानी चाहिए, फिर भी इंटरफ़ेस साइड इफेक्ट से ऐसी छेड़छाड़ की अनुमति देता है ...
Julien

यह भ्रामक है। यदि मैं लूप को अनियंत्रित करता हूं, तो यह तब काम करेगा जब मैं दो अलग-अलग चर np.zeros(3)में परिणाम को संग्रहीत करूंगा । यदि मैं परिणाम को संग्रहीत नहीं करता या एक ही चर का दो बार उपयोग नहीं करता, तो यह नहीं होगा। हो सकता है कि अधिक सुस्पष्ट ज्ञान वाला कोई व्यक्ति इस पर कुछ प्रकाश डाल सकता है।
सुस्ती

1
FYI करें, मैं विंडोज पर Python3 में एक ही चीज देखता हूं ...
जूलियन

जवाबों:


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)सभी में स्वीकार किया जाता है, क्योंकि आधिकारिक तौर पर, rmat3x1 1x3 या 3x3 होना चाहिए। वास्तव में, 1 डी rmatमें 3 तत्व नहीं होते हैं, जिसे पायथन आवरण द्वारा सही ढंग से खारिज कर दिया जाता है। मेरा संदेह यह है कि 2D ´rmat की पायथन स्तर पर ठीक से जाँच नहीं की गई है। सी कोड तब गलत आकार का पता लगाता है, एक त्रुटि कोड को वापस करने के अलावा कुछ भी नहीं करता है जिसे पायथन कोड चेक नहीं करता है।

वास्तव में एक 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फ़ंक्शन को कठोर गणना के बाद कुछ सार्थक मूल्यों को वापस करना है। इसके अलावा, ओपी में प्रस्तुत अजीब मूल्यों को शायद ही कचरा माना जा सकता है, क्योंकि वे सभी शून्य के बहुत करीब हैं।
sciroccorics

1
@sciroccorics क्या आप सहमत नहीं होंगे कि मेरा दूसरा स्निपेट बहुत सम्मोहक है?
पॉल पैंजर

मैंने इनपुट आकार की जांच के लिए एक पीआर प्रस्तुत किया है ।
कैटरी

3

निश्चित रूप से, यह रॉड्रिक्स फ़ंक्शन में एक बग है ...

यदि आप संबंधित डॉक को पढ़ते हैं , तो आप देख सकते हैं कि cv2.Rodrigues2 अलग-अलग इंटरफेस हैं:

एक जो C ++ इंटरफ़ेस की नकल करता है, जहां रोटेशन वेक्टर (और वैकल्पिक जैकोबियन) को संदर्भ द्वारा पारित किया जाता है और फ़ंक्शन द्वारा संशोधित किया जाता है।

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

और एक (अधिक पाइथोनिक) जहां रोटेशन वेक्टर और जेकोबियन को टुपल के रूप में वापस किया जाता है

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

आगे की जांच के बाद EDIT:

यह फ़ंक्शन अपेक्षा के अनुसार और भी अधिक छोटी है: पहले इंटरफ़ेस का उपयोग करते समय, पैरामीटर 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.

दूसरे शब्दों में, यह स्पष्ट रूप से एक बग रिपोर्ट की आवश्यकता है ...


अन्य उत्तर सही है। से समस्या आती है np.eye(4)। विधि की आवश्यकता है (3x1 या 1x3) रोटेशन वेक्टर या (3x3) रोटेशन मैट्रिक्स। यहाँ np.eye (4) फ़ंक्शन कुछ आकार के साथ dst बनाता है। लेकिन चूंकि इनपुट आकार गलत है, इसलिए विधि कुछ भी नहीं करती है और इसे इकाई रूप से छोड़ देती है। इसके अलावा, आप OpenCV के अप्रचलित संस्करण की ओर इशारा कर रहे हैं। मास्टर संस्करण का उपयोग करना या किसी विशिष्ट संस्करण को इंगित करना बेहतर है: docs.opencv.org देखें ।
बिल्ली 18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.