opencv

2010-10-18 20 views
6

का उपयोग कर कोनों के बिना आयताकार खोजें मेरे पास एक छवि है जहां मैं समोच्च ढूंढना चाहता हूं लेकिन मेरी छवि में "समोच्च" कोनों में नहीं है। क्या ऐसी कुछ युक्तियां हैं जिनका उपयोग मैं इस छवि में रेखाओं द्वारा उल्लिखित आयतों को खोजने में मदद के लिए कर सकता हूं? मैंने कोनों को बनाने के लिए सभी लाइनों को विस्तारित करने के बारे में सोचा था, लेकिन मुझे अन्य रूपों से अलग होने वाली लाइनों और यह निर्धारित करने के बारे में चिंता है कि मुझे किस अंतर में दिलचस्पी है। मैं ओपनसीवी के लिए बहुत नया हूं और मुझे छवि प्रसंस्करण के बारे में बहुत कुछ पता नहीं है। आप को भी मदद दे सकते हैं उसके लिए धन्यवाद। alt textopencv

उत्तर

4

मैंने अपना स्वयं का समाधान लागू करना समाप्त कर दिया। यह बहुत सुंदर नहीं है लेकिन यह काम पूरा हो जाता है। मुझे सुधारों के बारे में सुनने में दिलचस्पी होगी। HoughLines2 ने हमेशा मुझे लाइन सेगमेंट खोजने के लिए अच्छे नतीजे नहीं दिए और मुझे अलग-अलग परिदृश्यों के लिए थ्रेसहोल्ड वैल्यू के साथ गड़बड़ करनी पड़ी। इसके बजाय मैंने FindCountours का चयन किया जहां मैंने दो तत्वों के साथ समोच्चता ली, मुझे 1 पिक्सेल चौड़ी लाइनों की गारंटी दी जानी चाहिए। लाइनों को ढूंढने के बाद मैंने उनके माध्यम से पुनरावृत्त किया और आयतों को खोजने के लिए उन्हें ढूंढ लिया।

कहाँ अंक लाइन के एक * CvSeq है Endpoints

while(points->total>0){ 
    if(p1.x==-1&&p1.y==-1){ 
    cvSeqPopFront(points,&p1); 
    cvSeqPopFront(points,&p2); 
    } 

    if((pos=findClosestPoint(&p1,&p2, points,maxDist))>=0){ 
    p3 = (CvPoint*)cvGetSeqElem(points,pos); 
    pos2 = (pos%2==0)?pos+1:pos-1; //lines are in pairs of points 
    p4 = (CvPoint*)cvGetSeqElem(points,pos2); 

    if(isVertical(&p1,&p2) && isHorizontal(p3,p4)){ 
     printf("found Corner %d %d\n",p2.x,p3->y); 
    } else if(isHorizontal(&p1,&p2) && isVertical(p3,p4)){ 
     printf("found Corner %d %d\n",p3->x,p2.y); 
    } 

    memcpy(&p1,p3,sizeof(CvPoint)); 
    memcpy(&p2,p4,sizeof(CvPoint)); 
    cvSeqRemove(points, (pos>pos2)?pos:pos2); 
    cvSeqRemove(points, (pos>pos2)?pos2:pos); 
    } else { 
    p1.x=-1; 
    p1.y=-1; 
    } 
} 

int findClosestPoint (CvPoint *p1, CvPoint *p2, CvSeq *points, int maxDist) { 
    int ret = -1,i; 
    float dist, minDist = maxDist; 
    CvPoint* test; 
    int (*dirTest)(CvPoint *,CvPoint *); 

    if(isVertical(p1,p2)){ //vertical line 
     if(p2->y > p1->y) {//going down 
     dirTest = isBelow; 
     } else { // going up 
     dirTest = isAbove; 
     } 
    } else if (isHorizontal(p1,p2)){ //horizontal line 
     if(p2->x > p1->x) {//going right 
     dirTest = isRight; 
     } else { //going left 
     dirTest = isLeft; 
     } 
    } 

    for(i = 0; i < points->total; i++) 
    { 
     test = (CvPoint*)cvGetSeqElem(points, i); 
     if(dirTest(p2,test)){ //only test points in the region we care about 
     dist = sqrt(pow(test->x - p2->x,2)+pow(test->y - p2->y,2)); 
     if(dist<minDist){ 
      minDist = dist; 
      ret = i; 
     } 
     } 
    } 
    return ret; 
} 

int isVertical(CvPoint *p1, CvPoint *p2){ 
    return p1->x == p2->x; 
} 
int isHorizontal(CvPoint *p1, CvPoint *p2){ 
    return p1->y == p2->y; 
} 
int isRight(CvPoint *pt1, CvPoint *pt2){ 
    return pt2->x > pt1->x; 
} 
int isLeft(CvPoint *pt1, CvPoint *pt2){ 
    return pt2->x < pt1->x; 
} 
int isBelow(CvPoint *pt1, CvPoint *pt2){ 
    return pt2->y > pt1->y; 
} 
int isAbove(CvPoint *pt1, CvPoint *pt2){ 
    return pt2->y < pt1->y; 
} 
+0

यह कैसे काम करता है? मुझे लगता है कि यह निकटतम बिंदु पाता है और उन्हें लिंक करता है। और isVertical/etc फ़ंक्शंस का उपयोग करके, आप जांचते हैं कि यह लंबवत रेखा है या नहीं। –

+0

असल में मैं FindContours द्वारा प्राप्त लाइनों के माध्यम से पुन: प्रयास करता हूं। पहली पंक्ति के लिए मैं अपनी दिशा निर्धारित करता हूं, इसलिए मान लें कि यह बाएं से दाएं जा रहा है। मैं फिर शेष पंक्तियों में सबसे नज़दीकी बिंदु की तलाश करता हूं जो मेरी पहली पंक्ति के दाहिने बिंदु के दाईं ओर होगा। निकटतम बिंदु एक रेखा का एक अंत बिंदु होगा, मुझे दूसरा लगता है और फिर इस नई रेखा की दिशा निर्धारित करता है। यदि नई लाइन मेरी पहली पंक्ति के लिए लंबवत है तो मुझे एक कोने मिला है यदि यह नहीं है तो मैं केवल और लाइनों को ढूंढता रहता हूं जो अनिवार्य रूप से दाईं ओर अधिक होंगे। जैसा कि मुझे लाइनें मिलती हैं, मैं उन्हें सूची से बाहर ले जाता हूं। – john

+0

उपरोक्त उदाहरण में मुझे एक लंबवत रेखा मिलती है तो मैं एक अलग दिशा में आगे बढ़ जाऊंगा। तो मैं बाईं ओर दाएं से नीचे तक जा सकता हूं जहां मुझे केवल मेरी लाइन के ऊपर अंक मिलेगा। आखिर में findClosest को अब अंक नहीं मिलेगा क्योंकि मैं अधिकतम दूरी निर्दिष्ट करता हूं और मैं FindContours से प्राप्त एक और प्रारंभिक लाइन सेगमेंट पर जाऊंगा – john

4

Hough transform के साथ अपनी बाइनरी छवि में फिट लाइनें और ऑर्थोगोनली अंतरण लाइनों के आयत फिट करें।

+0

जैकब, त्वरित प्रतिक्रिया के लिए धन्यवाद। मैं houghlines2 से परिचित हूँ, लेकिन मैं वास्तव में 2 बिंदुओं के साथ compours के लिए cvFindContours का उपयोग कर रहा हूँ। हौफलाइन ने हमेशा अच्छे नतीजे नहीं दिए और मुझे थ्रेसहोल्ड के साथ बहुत गड़बड़ करनी पड़ी। मेरा मानना ​​है कि समस्या का वास्तविक क्रूक्स आयताकारों को फिट कर रहा है, मैं एक अच्छी विधि नहीं समझ पाया लेकिन मैंने कुछ ऐसा किया जो मैं पोस्ट करूंगा। – john

0

hough transform का उपयोग करके आप लाइनों को निकालने में सक्षम होंगे। फिर आप आयत की स्थिति का अनुमान लगाने के लिए इन पंक्तियों के चौराहे की गणना कर सकते हैं।

+0

मैंने लाइनों को लेने और उन्हें बाहर निकालने और चौराहे खोजने के बारे में सोचा लेकिन यह मुझे कुछ नकली आयताकारों के साथ छोड़ देता है जिन्हें मुझे बाहर करना होगा। यह अधिक आयत के साथ बदतर हो जाएगा। मैंने एक कस्टम समाधान बनाया जो बहुत ही सुरुचिपूर्ण नहीं है लेकिन मैं पोस्ट करूंगा। – john

1

तुम भी अनुकूलन समस्या के रूप में प्रस्तुत करने की कोशिश कर सकता है। यदि आप रोटेशन (एक्स, वाई, चौड़ाई, ऊंचाई, रोटेशन) शामिल करते हैं तो आयताकार को 4 डी स्टेट वेक्टर (एक्स, डब्ल्यू, चौड़ाई, ऊंचाई) या 5 डी वेक्टर के रूप में परिभाषित किया जाता है। अपने वर्तमान राज्य के लिए आप इष्टतम राज्य में अभिसरण करने के लिए हफ़ लाइनों के परिणाम की ओर एक ढाल वंशज बना सकते हैं। अन्य विकल्प रैखिक कम से कम वर्गों का उपयोग कर रहा है: http://people.inf.ethz.ch/arbenz/MatlabKurs/node88.html