2012-07-27 22 views
16

मेरे पास मॉडल छवि पर ऑब्जेक्ट है। मैं मॉडल छवि पर ऑब्जेक्ट और लक्ष्य छवि पर ऑब्जेक्ट के बीच रूपांतरण (विस्थापन, स्केल, रोटेशन) की गणना करना चाहता हूं। मैं धारणा बनाना चाहता हूं कि वस्तु को 2 डी के रूप में माना जा सकता है, इसलिए केवल 2 डी परिवर्तनों की गणना की जानी चाहिए।अंक के दो सेट के बीच परिवर्तन

सबसे पहले मैं मैन्युअल रूप से सहायता प्राप्त करना चाहता हूं। उपयोगकर्ता मॉडल छवि पर आधार बिंदु का चयन करता है और फिर लक्षित छवि पर लक्ष्य बिंदु का चयन करता है। अंक की संख्या उपयोगकर्ता द्वारा परिभाषित की जानी चाहिए (लेकिन कम से कम 2-3 अंक से कम नहीं)। जब अंक अलग-अलग जानकारी देते हैं, तो परिवर्तन औसत होना चाहिए और उदाहरण के लिए मिलान की गुणवत्ता की गणना की जा सकती है।

तो प्रश्न बिंदुओं के दो सेटों के रूपांतरण की गणना करने के बजाए हैं, लेकिन जैसा कि मैं इसे छवि पर करना चाहता हूं, मैंने छवि प्रसंस्करण टैग जोड़ा है।

विशेष रूप से स्वागत है कोड या छद्म कोड के कुछ टुकड़ों के साथ संदर्भ और सलाह हैं।

दो बिंदुओं के साथ यह बहुत आसान मुद्दा है, केवल घूर्णन, स्केल और लाइन के विस्थापन को लिया जाना चाहिए, लेकिन इसे और अधिक अंक के साथ कैसे करना है, और औसत के साथ और कुछ गुणवत्ता कारकों की गणना करना।

वर्तमान समाधान है:

void transformFnc(std::vector<PointF> basePoints, std::vector<PointF> targetPoints, 
        PointF& offset, double rotation, double scale) 
{ 
    std::vector<Line> basePointsLines; 
    std::vector<Line> targetPointsLines; 
    assert(basePoints.size() == targetPoints.size()); 
    int pointsNumber = basePoints.size(); 

    for(int i = 0; i < pointsNumber; i++) 
    { 
     for(int j = i + 1; j < pointsNumber; j++) 
     { 
      basePointsLines.push_back(Line(basePoints[i], basePoints[j])); 
      targetPointsLines.push_back(Line(targetPoints[i], targetPoints[j])); 
     } 
    } 
    std::vector<double> scalesVector; 
    std::vector<double> rotationsVector; 
    double baseCenterX = 0, baseCenterY = 0, targetCenterX = 0, targetCenterY = 0; 
    for(std::vector<Line>::iterator it = basePointsLines.begin(), i = targetPointsLines.begin(); 
     it != basePointsLines.end(), i != targetPointsLines.end(); it++, i++) 
    { 
     scalesVector.push_back((*i).length()/(*it).length()); 
     baseCenterX += (*it).pointAt(0.5).x(); 
     baseCenterY += (*it).pointAt(0.5).y(); 
     targetCenterX += (*i).pointAt(0.5).x(); 
     targetCenterY += (*i).pointAt(0.5).y(); 
     double rotation; 
     rotation = (*i).angleTo((*it)); 
     rotationsVector.push_back(rotation); 
    } 
    baseCenterX = baseCenterX/pointsNumber; 
    baseCenterY = baseCenterY/pointsNumber; 
    targetCenterX = targetCenterX/pointsNumber; 
    targetCenterY = targetCenterY/pointsNumber; 

    offset = PointF(targetCenterX - baseCenterX, targetCenterY - baseCenterY); 
    scale = sum(scalesVector)/scalesVector.size(); 
    rotation = sum(rotationsVector)/rotationsVector.size(); 
} 

केवल अनुकूलन मैं इस कोड में पा सकते हैं तराजू और रोटेशन उन मूल्यों को जो बाकी हिस्सों से बहुत ज्यादा अलग से खत्म करने के लिए है।

मैं समाधान प्रस्तावों के कोड या छद्म कोड की तलाश में हूं। यह कुछ कोडों के संदर्भ भी हो सकता है।

तो जवाब से जहाँ तक मुझे पता है कि:

  • RANSAC एल्गोरिथ्म इस्तेमाल किया जा सकता
  • मैं कम से कम वर्ग भावना
+0

क्या आप अन्य परिवर्तनों को खींचना और कतरन करना चाहते हैं? –

+0

नहीं। धारणा यह है कि यह ठोस वस्तु है। कोई परिप्रेक्ष्य, खींचने, कताई। – krzych

+1

संभावित डुप्लिकेट [एक त्रिकोण को दूसरे त्रिकोण में बदलें] (http://stackoverflow.com/questions/1114257/transform-a-triangle-to-another-triangle) – finnw

उत्तर

20

पहले एक 3x3 affine परिवर्तन मैट्रिक्स के साथ एक सरल affine परिवर्तन में समस्या सामान्यीकरण: अर्थात

[M11 M12 M13] 
[M21 M22 M23] 
[M31 M32 M33] 

जब से हम पहले से ही पता है कि तीसरी पंक्ति हमेशा रहेंगे [0 0 1] हम बस यह ध्यान न दें।

अब हम निम्नलिखित मैट्रिक्स समीकरण

[xp0]  [x0 y0 1 0 0 0 ] 
[yp0]  [0 0 0 x0 y0 1 ]  [M11] 
[xp1]  [x1 y1 1 0 0 0 ]  [M12] 
[yp1] = [0 0 0 x1 y1 1 ] * [M13] 
[xp2]  [x2 y2 1 0 0 0 ]  [M21] 
[yp2]  [0 0 0 x2 y2 1 ]  [M22] 
[xp3]  [x3 y3 1 0 0 0 ]  [M23] 
[yp3]  [0 0 0 x3 y3 1 ] 

के रूप में समस्या का वर्णन कर सकते हैं जहां XP और YP अनुमान निर्देशांक और x और y कर रहे हैं मूल निर्देशांक।

के इस

proj = M * trans 

हम तब तक

trans = pinv(M) * proj 

जहां pinv छद्म उल्टा होता है एक कम से कम परिवर्तन के लिए फिट वर्गों की गणना कर सकते कहते हैं।

यह हमें एक एफ़िन रूपांतरण प्रदान करता है जो कम से कम वर्गों में दिए गए अंकों को सर्वोत्तम रूप से फिट करता है।

अब स्पष्ट रूप से यह कतरनी, फ्लिप के साथ-साथ गैर-वर्दी स्केलिंग को समन्वयित करेगा जो आप नहीं चाहते थे इसलिए हमें कतरनी से बचने के लिए किसी भी तरह से एफ़िन रूपांतरण को सीमित करने की आवश्यकता है। यह काफी आसान साबित होता है, हम घूर्णन (वेक्टर की दिशा) और स्केलिंग (वेक्टर की परिमाण) का वर्णन करने के लिए एक वेक्टर का उपयोग कर सकते हैं, अन्य वेक्टर बस ऑर्थोगोनल होंगे। इससे दो स्वतंत्रता की डिग्री कम हो जाती है।

M21 = -M12 
M22 = M11 

तो

[xp0]  [x0 y0 1 0] 
[yp0]  [y0 -x0 0 1] 
[xp1]  [x1 y1 1 0]  [M11] 
[yp1] = [y1 -x1 0 1] * [M12] 
[xp2]  [x2 y2 1 0]  [M13] 
[yp2]  [y2 -x2 0 1]  [M23] 
[xp3]  [x3 y3 1 0] 
[yp3]  [y3 -x3 0 1] 

को कम करने और M12 और M11 से M21 और M22 की गणना हम ऊपर मैट्रिक्स समीकरण को हल किया है के बाद।

+0

इस विधि में सभी बिंदुओं को समान रूप से माना जाता है हालांकि यह शोर के लिए मजबूत नहीं है। विधि के विवरण भी मैं इस प्रश्न के लिए मिलान करने के लिए अंक कैसे प्राप्त करता हूं, यह बहुत महत्वपूर्ण है। – krzych

+3

आपके प्रश्न में आपने केवल उस मामले के बारे में पूछा जहां मिलान मैन्युअल रूप से मैन्युअल रूप से किया गया था। यह शोर के लिए मजबूत है क्योंकि यह एक अतिरंजित प्रणाली पर कम से कम वर्गों का उपयोग करता है, जितना अधिक अंक आप मैच करेंगे उतना अधिक शोर का औसत होगा। यदि शोर वितरण सभी बिंदुओं के लिए समान है, तो यह समाधान पर्याप्त है, यदि आप पहले से ही जानते हैं कि विभिन्न बिंदुओं के लिए शोर अनुपात आप ज्ञात शोर अनुपात के अनुसार 'proj' और' M' को स्केल करके बेहतर कर सकते हैं। – wich

+0

ठीक है। समझा। इस विधि में शोर वितरण एक ही दुर्भाग्यपूर्ण नहीं होगा। क्या आप बिंदुओं के बीच लाइनों का उपयोग करके मेरे वर्तमान समाधान में प्रस्तावित विधि की त्रुटियों की तुलना कर सकते हैं? मेरी विधि में मैं अंक को खत्म करके शोर को खत्म कर सकता हूं जो दूसरों की तुलना में अलग घूर्णन और स्केल देता है। – krzych

1

आपका परिवर्तन में कंप्यूटिंग एल्गोरिथ्म को बदलने कुछ affine के लिए देखने की जरूरत है एक एफ़िन रूपांतरण है, जिसे 3 * 3 मैट्रिक्स में लिखा जा सकता है। तो आपकी समस्या मूल रूप से कम से कम-वर्ग-त्रुटि एफ़िन रूपांतरण को गणनाओं के एक सेट से दूसरों के लिए गणना करने के लिए है।

यह समस्या आम कम्प्यूटेशनल ज्यामिति साहित्य में काफी हल हो गई है। एक अच्छी क्लासिक पुस्तक यह है: http://www.robots.ox.ac.uk/~vgg/hzbook/hzbook1.html (कोई विज्ञापन नहीं, यह ज्यादातर लोगों के लिए संदर्भ पुस्तक है)। आपको 2 डी और 3 डी ज्यामिति के बारे में सारी जानकारी मिल जाएगी। "एफ़िन ट्रांसफॉर्मेशन एलएमएसई" जैसे शब्दों पर एक त्वरित Google आपको जानकारी और शायद कोड भी देगा।

इसके अलावा, आप अन्य प्रकार के एल्गोरिदम, मजबूत वाले, जैसे RANSAC का भी उपयोग कर सकते हैं। आपके आवेदन के आधार पर, उस दिशा में आगे बढ़ना दिलचस्प हो सकता है।

+0

जहां तक ​​मुझे पता है कि एफ़िन रूपांतरण मैं जो वर्णन करता हूं उससे अलग कुछ है। यह खींचने, कतरनी आदि लेता है – krzych

+0

सही यह एक सामान्यीकरण है। लेकिन जिस तरह से आप पदों से समीकरण प्राप्त करते हैं वही है, आपके पास सिर्फ एक और बाधा है (कोई कतरनी नहीं)। – Bentoy13

2

सादगी के लिए, मान लें कि आपके इनपुट x1,...,xn और आउटपुट y1,...,yn जटिल संख्याएं हैं।

  1. आप कंप्यूटिंग avg(y) - avg(x) द्वारा औसत विस्थापन की गणना कर सकते हैं और एक बार यह हो जाए आप x और y इतना है कि वे 0 के आसपास केंद्रित कर रहे हैं, दोनों के लिए औसत घटाना कर सकते हैं।

  2. अब आप एक घूर्णन और स्केल खोजना चाहते हैं। आप एक जटिल संख्या z दोनों का प्रतिनिधित्व कर सकते हैं, ताकि x*z जितना संभव हो सके y पर हो। ताकि आप को हल करने के लिए z ऐसी है कि x*z कम से कम वर्ग अर्थों में अधिक से अधिक निकट y है क्लासिक रेखीय बीजगणित का उपयोग कर सकते: लेकिन x*z एक आर की (वास्तविक) -linear समारोह निर्देशांक z की (zx,zy) है।

इसे सभी को एक साथ रखकर, यह आपको कम से कम वर्ग भावना में इष्टतम परिवर्तन देता है।

6

मैं Iterative closest point एल्गोरिदम को आज़मा दूंगा।

Here आपको स्केलिंग के साथ कार्यान्वयन मिल रहा है। (SICP)

एक अन्य उपयोगी link

+0

आपके द्वारा प्रदान किया गया दूसरा लिंक स्केल के लिए प्रतिरोधी है। मुझे भी पैमाने की गणना करने की आवश्यकता है। क्या आप जानते हैं कि गणना ट्रांसफॉर्म कोड से स्केल कैसे प्राप्त करें? – krzych

+0

यह इस समस्या के लिए कैननिकल, अच्छी तरह से समझने वाला दृष्टिकोण है। इसका उपयोग फीचर आधारित पैनोरमा सिलाई सॉफ्टवेयर में किया जाता है क्योंकि यह बहुत प्रभावी है। – Kaganar

+0

यह दृष्टिकोण सुविधाओं के बड़े पैमाने पर निर्भर करता है। यदि सुविधाओं को वितरित नहीं किया जाता है तो समान रूप से त्रुटि बड़ी हो जाती है। – krzych

0

अधिक simple and clear code in Matlab आप को बदलने दे सकता है कि।

और more complex C++ code(using VXL lib) पाइथन और मैटलैब रैपर के साथ शामिल थे।

या आप कुछ संशोधित आईसीपी (पुनरावर्तक निकटतम बिंदु) एल्गोरिदम का उपयोग कर सकते हैं जो शोर के लिए मजबूत है।