2011-11-11 11 views
7

मैं ओपनसीवी में एक पैनोग्राफी/पैनोरमा एप्लिकेशन पर काम कर रहा हूं और मैंने एक समस्या में भाग लिया है जिसे मैं वास्तव में समझ नहीं सकता। एक पैनोरामा तस्वीर कैसा दिखता है, इस बारे में एक विचार के लिए, यहां पैनोग्राफी विकिपीडिया आलेख पर एक नज़र डालें: http://en.wikipedia.org/wiki/PanographyOpenCV findHomography Issue

अब तक, मैं कई छवियां ले सकता हूं, और किसी भी छवि को बनाने के दौरान उन्हें एक साथ सिलाई कर सकता हूं, मुझे एक संदर्भ छवि पसंद है; मेरा मतलब यह है कि मेरा मतलब थोड़ा सा है।

An example Panography image I've created

हालांकि

, जैसा कि आप देख सकते हैं - यह मुद्दों का एक बहुत कुछ है। प्राथमिक मुझे सामना करना पड़ रहा है कि छवियां कटौती कर रही हैं (पुनः: दूर दाएं छवि, छवियों के शीर्ष)। यह बताने के लिए क्यों यह हो रहा है, मैं अंक कि मिलान किया गया है आकर्षित कर देंगे, और जहां परिवर्तन खत्म हो जाएगा के लिए रेखा खींचने:

The image matches

कहाँ बाईं छवि संदर्भ छवि है, और सही छवि का अनुवाद होने के बाद छवि है (नीचे मूल) - मैंने छवि को हाइलाइट करने के लिए हरे रंग की रेखाएं खींची हैं। छवि निम्नलिखित कोने अंक हैं:

TL: [234.759, -117.696] 
TR: [852.226, -38.9487] 
BR: [764.368, 374.84] 
BL: [176.381, 259.953] 

तो मुख्य समस्या मैं यह है कि बाद परिप्रेक्ष्य छवि बदल दिया गया है:

Original Image

तो तरह ग्रस्त नुकसान:

Cut up image

अब पर्याप्त छवियां, कुछ कोड। करने के लिए

/* calculate the matches */ 
for(int i = 0; i < descriptors_thisImage.rows; i++) { 
    double dist = matches[i].distance; 
    if(dist < min_dist) min_dist = dist; 
    if(dist > max_dist) max_dist = dist; 
} 

/* calculate the good matches */ 
for(int i = 0; i < descriptors_thisImage.rows; i++) { 
    if(matches[i].distance < 3*min_dist) { 
     good_matches.push_back(matches[i]); 
    } 
} 

यह वह जगह है सुंदर मानक है, और:

मैं एक cv::SurfFeatureDetector, cv::SurfDescriptorExtractor और cv::FlannBasedMatcher उपयोग कर रहा हूँ उन बिंदुओं के सभी प्राप्त करने के लिए, और मैं मैच और ऐसा करके अधिक महत्वपूर्ण बात यह अच्छा मैचों निम्नलिखित गणना ऐसा करने मैं ट्यूटोरियल यहाँ पाया बाद: http://opencv.itseez.com/trunk/doc/tutorials/features2d/feature_homography/feature_homography.html

एक-दूसरे के ऊपर छवियों नकल के लिए, मैं निम्न विधि का उपयोग

+०१२३५१६४१०६१ (जहां img1 और img2 std::vector<cv::Point2f> कर रहे हैं)
/* set the keypoints from the good matches */ 
for(int i = 0; i < good_matches.size(); i++) { 
    img1.push_back(keypoints_thisImage[ good_matches[i].queryIdx ].pt); 
    img2.push_back(keypoints_referenceImage[ good_matches[i].trainIdx ].pt); 
} 

/* calculate the homography */ 
cv::Mat H = cv::findHomography(cv::Mat(img1), cv::Mat(img2), CV_RANSAC); 

/* warp the image */ 
cv::warpPerspective(thisImage, thisTransformed, H, cv::Size(thisImage.cols * 2, thisImage.rows * 2), cv::INTER_CUBIC); 

/* place the contents of thisImage in gsThisImage */ 
thisImage.copyTo(gsThisImage); 

/* set the values of gsThisImage to 255 */ 
for(int i = 0; i < gsThisImage.rows; i++) { 
    cv::Vec3b *p = gsThisImage.ptr<cv::Vec3b>(i); 
    for(int j = 0; j < gsThisImage.cols; j++) { 
     for(int grb=0; grb < 3; grb++) { 
      p[j][grb] = cv::saturate_cast<uchar>(255.0f); 
     } 
    } 
} 

/* convert the colour to greyscale */ 
cv::cvtColor(gsThisImage, gsThisImage, CV_BGR2GRAY); 

/* warp the greyscale image to create an image mask */ 
cv::warpPerspective(gsThisImage, thisMask, H, cv::Size(thisImage.cols * 2, thisImage.rows * 2), cv::INTER_CUBIC); 

/* stitch the transformed image to the reference image */ 
thisTransformed.copyTo(referenceImage, thisMask); 

तो, मेरे पास निर्देशांक हैं कि युद्ध की गई छवि कहां खत्म हो रही है, मेरे पास ऐसे अंक हैं जो इन परिवर्तनों के लिए उपयोग की जाने वाली सजातीय मैट्रिक्स बनाते हैं - लेकिन मुझे यह नहीं पता कि मुझे कैसे जाना चाहिए इन छवियों का अनुवाद करना ताकि वे काट नहीं सकें। किसी भी मदद या पॉइंटर्स की बहुत सराहना की जाती है!

उत्तर

5

सबसे पहले, आपने नए जोड़े गए सिलाई मॉड्यूल का उपयोग क्यों नहीं किया? यह वही काम करता है जिसे आप करने की कोशिश कर रहे हैं।

दूसरा, यदि आप अपने कोड को जारी रखना चाहते हैं, तो इसे सही करने के लिए यह आसान है। होमोग्राफी मैट्रिक्स में, अनुवाद अंतिम कॉलम पर मानों का प्रतिनिधित्व करते हैं।

a11 a12 a13 t1 
a21 a22 a23 t2 
a31 a32 a33 t3 
a41 a42 a43 1 

(आप एक 3x3 मैट्रिक्स है, तो आप a13..a43 स्तंभ और a41..1 पंक्ति याद करेंगे। A33 जाएगा (चाहिए) 1 हो जाते हैं)।

तो, आपको यह पता लगाने के लिए क्या करना है कि आपको अंतिम कॉलम में क्या रखा जाना चाहिए ताकि आप छवियों को गठबंधन कर सकें।

यह पोस्ट भी देखें जो कैमरे के पैरामीटर को जानते समय, एक होमोग्राफी बनाने के बारे में बताता है (किसी भी तरह की विपरीत समस्या)। यह आपको मैट्रिक्स मानों की भूमिका को समझने में मदद करेगा।

Opencv virtually camera rotating/translating for bird's eye view

और टिप्पणी है कि सब कुछ मैं तुम्हें अंतिम स्तंभ के बारे में बताया है केवल अनुमानित है, क्योंकि अंतिम स्तंभ में मान वास्तव में अनुवाद प्लस कुछ (मामूली) कारक हैं।

+1

आह, मैं देखता हूं - इससे पहले कि मैं cv :: warp चलाता हूं, संभवतः मैं होलोग्रफ़ी में मानों को संपादित करता हूं? यह अब इतना स्पष्ट है! बहुत बहुत धन्यवाद! इसके अलावा, मैं छवि सिलाई मॉड्यूल में देखूंगा और इसे एक विकल्प के रूप में जोड़ूंगा (अंतरों की तुलना करने के लिए जीपीयू और सीपीयू का उपयोग करके) - बस ओपनसीवी सीखने की कोशिश कर रहा हूं। :-) – krslynx

+1

फिर से धन्यवाद! http://krslynx.com/images/ – krslynx

+1

अपने अच्छे नतीजे देखने के लिए खुशी हुई! – Sam

1

एक बार जब आप मेट्रिसिस पाते हैं तो आपको कोनों के लिए रूपांतरणों की गणना करना चाहिए और ट्रांसफॉर्म किए गए बिंदुओं के लिए न्यूनतम और वाई एक्स मानों को एकत्र करना चाहिए।

बार जब आप इस सीमांकन बॉक्स सिर्फ (-xmin,-ymin) द्वारा सभी मैट्रिक्स अनुवाद और परिणाम के लिए ऐसी छवि है (xmax-xmin) विस्तृत और (ymax-ymin) लंबा आवंटित और फिर उस में सब बदल छवियों आकर्षित किया है।

इस दृष्टिकोण के साथ आपको सिलाई के आसपास काले क्षेत्र होंगे लेकिन कोई क्लिपिंग नहीं होगी।

सिलाई में निहित सबसे बड़ा आयताकार (स्वचालित रूप से कोई काला क्षेत्र और न्यूनतम क्लिपिंग वाला पूर्ण विलय छवि प्राप्त करने के लिए) को स्वचालित रूप से ढूंढने के लिए इसे लागू करने के लिए थोड़ा अधिक परेशान है।