2012-06-28 7 views
20

यह सवाल OpenCV कार्यों findHomography पर है, getPerspectiveTransform & getAffineTransformfindHomography, getPerspectiveTransform, और getAffineTransform

  1. क्या findHomography और getPerspectiveTransform के बीच का अंतर है?। प्रलेखन से मेरी समझ यह है कि getPerspectiveTransform 4 पत्राचार (जो एक होमोग्राफी/परिप्रेक्ष्य परिवर्तन की गणना करने के लिए न्यूनतम आवश्यक है) का उपयोग करके परिवर्तन की गणना करता है, जहां findHomography ट्रांसफॉर्म की गणना करता है भले ही आप 4 से अधिक पत्राचार प्रदान करते हैं (संभवतः कम से कम वर्गों की तरह कुछ उपयोग करना तरीका?)। क्या यह सही है? (जो मामले में एकमात्र कारण OpenCV अभी भी पुराना होना चाहिए getPerspectiveTransform समर्थन जारी?)

  2. मेरा अगला चिंता का विषय है कि मैं अगर वहाँ एक Affine परिवर्तन की गणना के लिए findHomography के लिए एक बराबर है जानना चाहते हैं? यानी एक ऐसा फ़ंक्शन जो रूपांतरण की गणना और गठबंधन करने के लिए कम से कम वर्ग या समकक्ष मजबूत विधि का उपयोग करता है। प्रलेखन के अनुसार getAffineTransform केवल 3 पत्राचारों में लेता है (जो एक एफ़िन ट्रांसफॉर्म की गणना करने के लिए आवश्यक न्यूनतम मिनट है)।

बेस्ट,

+1

हो सकता है कि [estimateRigidTransform] (http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking।एचटीएमएल # अनुमानित फिल्टर ट्रांसफॉर्म) आपकी आवश्यकताओं के अनुरूप होगा। – cgat

उत्तर

24

क्यू # 1: ठीक है, findHomography सबसे अच्छा लगता है अंक के दो सेट के बीच बदलने के लिए कोशिश करता है। यह RANSAC नामक कम से कम वर्गों से अधिक स्मार्ट का उपयोग करता है, जिसमें आउटलाइजर्स को अस्वीकार करने की क्षमता होती है - यदि आपके डेटा बिंदुओं का कम से कम 50% + 1 ठीक है, तो RANSAC उन्हें ढूंढने और विश्वसनीय रूपांतरण बनाने के लिए सर्वोत्तम प्रयास करेगा।

GetPerspectiveTransform में रहने के लिए बहुत सारे उपयोगी कारण हैं - यह होमोोग्राफी खोजने का आधार है, और यह कई परिस्थितियों में उपयोगी है जहां आपके पास केवल 4 अंक हैं, और आप जानते हैं कि वे सही हैं। FindHomography आमतौर पर स्वचालित रूप से पता चला अंकों के सेट के साथ प्रयोग किया जाता है - आप उनमें से कई पा सकते हैं, लेकिन कम आत्मविश्वास के साथ। getPerspectiveTransform अच्छा है जब आप निश्चित रूप से 4 कोनों के लिए oww करते हैं - जैसे मैन्युअल अंकन, या आयताकार का स्वचालित पता लगाना।

क्यू # 2 एफ़िन ट्रांसफॉर्म के लिए कोई समकक्ष नहीं है। आप खोजोग्राफी का उपयोग कर सकते हैं, क्योंकि एफ़िन ट्रांसफॉर्म होमोग्राफ का सबसेट है।

8

मैं सब कुछ @ vasile लिखा है के साथ सहमत हूं। मैं तो बस कुछ टिप्पणियों जोड़ना चाहते हैं:

getPerspectiveTransform() और getAffineTransform() या अंक (क्रमशः), कि सही पत्राचार होने के लिए जाना जाता है पर काम करने के लिए हैं। वास्तविक कैमरे के साथ ली गई वास्तविक जीवन छवियों पर, आप कभी भी सटीक नहीं हो सकते हैं, न कि स्वचालित और न ही संबंधित बिंदुओं के मैन्युअल अंकन के साथ।

हमेशा आउटलेटर्स होते हैं। बस बिंदुओं के माध्यम से वक्र फिट करने के इच्छुक साधारण मामले देखें (उदाहरण के लिए शोर y1 = f(x) = 3.12x + gauss_noise या y2 = g(x) = 0.1x^2 + 3.1x + gauss_noise के साथ जनरेटिव समीकरण लें): दोनों मामलों में बिंदुओं का अनुमान लगाने के लिए एक अच्छा वर्गबद्ध कार्य ढूंढना अधिक आसान होगा एक अच्छा रैखिक एक। Quadratic एक overkill हो सकता है, लेकिन ज्यादातर मामलों में (outliers को हटाने के बाद) नहीं होगा, और यदि आप एक सीधी रेखा फिट करना चाहते हैं तो आप बेहतर यकीन है कि यह सही मॉडल है, अन्यथा आप अनुपयोगी परिणाम प्राप्त करने जा रहे हैं।

कहा, यदि आप जोर से यकीन है कि कि Affine बदलना सही एक है, यहाँ है एक सुझाव है:

  • उपयोग findHomography, कि RANSAC कार्यक्षमता के लिए में शामिल किया गया है, से छुटकारा पाने के आउटलाइजर्स और छवि परिवर्तन का प्रारंभिक अनुमान
  • 3 सही मिलान-संवाद (जो कि होमोग्राफी के साथ फिट है) का चयन करें, या पहली छवि से दूसरे बिंदु (होमोग्राफी का उपयोग करके) 3 अंक दोहराएं
  • getAffineTransform()
  • findAffine() में उन सभी 3 मैचों का उपयोग करें जो आप चाहते हैं - और voila!
+0

क्या सर्वोत्तम "एफ़िन" मैट्रिक्स खोजने का कोई तरीका है? मैं होमोग्राफी की आखिरी पंक्ति को [0, 0, 1] होने के लिए मजबूर करना चाहता हूं। – Royi

+1

@Drazick मैंने लिखा है "एल्गोरिदम" लगभग यह करता है - यह outliers से छुटकारा पाने के लिए खोजोग्राफी का उपयोग करता है और इसलिए कि आपको अपने स्वयं के RANSAC को कोड करने की आवश्यकता नहीं है, और आप किसी भी 3 अंक पर getAffineTransform() का उपयोग कर सकते हैं एक करीबी से सबसे अच्छा affine प्राप्त करें। Alternatevley, आप कोर फंक्शन के रूप में getPerspectiveTransform() के बजाय getAffineTransform() के साथ अपने स्वयं के RANSAC एल्गोरिदम को कोड कर सकते हैं। – penelope

+0

@penleope, मुझे एक समाधान मिला कि एसवीडी का उपयोग करके सर्वोत्तम (एल 2 बुद्धि) एफ़िन ट्रांसफॉर्म को कैसे सर्वोत्तम तरीके से समझा जाता है। – Royi

3

पुन: प्रश्न 2, अनुमान RigidTransform getAffineTransform के oversampled समकक्ष है। मुझे नहीं पता कि यह ओसीवी में था जब यह पहली बार पोस्ट किया गया था, लेकिन यह 2.4 में उपलब्ध है।

1

अति निर्धारित समीकरणों की प्रणाली के लिए एफ़िन ट्रांसफॉर्म खोजने के लिए एक आसान समाधान है।

  1. नोट सामान्य रूप में एक Affine परिणत कि एक छद्म उलटा या इसी तरह की तकनीक का उपयोग करके रेखीय समीकरण कुल्हाड़ी = बी के ओवर-द निर्धारित प्रणाली के लिए एक समाधान पाता है, तो

एक्स = (ए.ए. टी) -1 एक टी बी

इसके अलावा, यह एक सरल कॉल द्वारा कोर openCV कार्यक्षमता में नियंत्रित किया जाता है हल करने के लिए (ए, बी, एक्स)।

  1. Affine के कोड को अच्छी तरह समझ opencv/मॉड्यूल/imgproc/src/imgwarp.cpp में परिणत:

    एक: यह वास्तव में सिर्फ दो काम करता है। सिस्टम एएक्स = बी बनाने के लिए इनपुट पुनर्व्यवस्थित करता है;

    बी। फिर कॉल (ए, बी, एक्स) हल;

नोट: उपेक्षा openCV कोड में समारोह टिप्पणियां - वे भ्रमित कर रहे हैं और मैट्रिक्स में तत्वों की वास्तविक आदेश प्रतिबिंबित नहीं करते। आप को सुलझाने रहे हैं, तो [u, v] '= Affine * [एक्स, वाई, 1] पुनर्व्यवस्था है:

  x1 y1 1 0 0 1 
     0 0 0 x1 y1 1 
     x2 y2 1 0 0 1 
    A = 0 0 0 x2 y2 1 
     x3 y3 1 0 0 1 
     0 0 0 x3 y3 1 

    X = [Affine11, Affine12, Affine13, Affine21, Affine22, Affine23]’ 

     u1 v1 
    B = u2 v2 
     u3 v3 

तुम सब करने की ज़रूरत है अधिक अंक जोड़ना है। हल करने के लिए (ए, बी, एक्स) ओवर-निर्धारित सिस्टम पर काम करने के लिए DECOMP_SVD पैरामीटर जोड़ें। विषय पर पावरपॉइंट स्लाइड्स देखने के लिए, इस link का उपयोग करें। आप कंप्यूटर दृष्टि के संदर्भ में छद्म प्रतिलोम के बारे में अधिक जानने के लिए चाहते हैं, तो सबसे अच्छा स्रोत है: ComputerVision, देखने के अध्याय 15 और परिशिष्ट सी

आप अभी भी अधिक अंक देखने को जोड़ने का तरीका अनिश्चित हैं, तो मेरी नीचे दिए गए कोड:

// extension for n points; 
cv::Mat getAffineTransformOverdetermined(const Point2f src[], const Point2f dst[], int n) 
{ 
    Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data); // output 
    double* a = (double*)malloc(12*n*sizeof(double)); 
    double* b = (double*)malloc(2*n*sizeof(double)); 
    Mat A(2*n, 6, CV_64F, a), B(2*n, 1, CV_64F, b); // input 

    for(int i = 0; i < n; i++) 
    { 
     int j = i*12; // 2 equations (in x, y) with 6 members: skip 12 elements 
     int k = i*12+6; // second equation: skip extra 6 elements 
     a[j] = a[k+3] = src[i].x; 
     a[j+1] = a[k+4] = src[i].y; 
     a[j+2] = a[k+5] = 1; 
     a[j+3] = a[j+4] = a[j+5] = 0; 
     a[k] = a[k+1] = a[k+2] = 0; 
     b[i*2] = dst[i].x; 
     b[i*2+1] = dst[i].y; 
    } 

    solve(A, B, X, DECOMP_SVD); 
    delete a; 
    delete b; 
    return M; 
} 

// call original transform 
vector<Point2f> src(3); 
vector<Point2f> dst(3); 
src[0] = Point2f(0.0, 0.0);src[1] = Point2f(1.0, 0.0);src[2] = Point2f(0.0, 1.0); 
dst[0] = Point2f(0.0, 0.0);dst[1] = Point2f(1.0, 0.0);dst[2] = Point2f(0.0, 1.0); 
Mat M = getAffineTransform(Mat(src), Mat(dst)); 
cout<<M<<endl; 
// call new transform 
src.resize(4); src[3] = Point2f(22, 2); 
dst.resize(4); dst[3] = Point2f(22, 2); 
Mat M2 = getAffineTransformOverdetermined(src.data(), dst.data(), src.size()); 
cout<<M2<<endl; 
संबंधित मुद्दे