2012-04-25 16 views
6

पर रोटेशन/अनुवाद वेक्टर कुछ बुनियादी संवर्धित वास्तविकता करने के लिए ओपनसीवी का उपयोग करने की कोशिश कर रहा हूं। जिस तरह से मैं इसके बारे में जा रहा हूं वह कैमरे की छवि से बिंदुओं का एक सेट प्राप्त करने के लिए findChessboardCorners का उपयोग कर रहा है। फिर, मैं z = 0 विमान के साथ एक 3 डी क्वाड बनाता हूं और इमेज किए गए बिंदुओं और प्लानर बिंदुओं के बीच एक होमोग्राफी प्राप्त करने के लिए solvePnP का उपयोग करता हूं। उस से, मुझे लगता है कि मुझे एक मॉडलव्यू मैट्रिक्स स्थापित करने में सक्षम होना चाहिए जो मुझे छवि के शीर्ष पर दाएं पॉज़ के साथ घन प्रस्तुत करने की अनुमति देगा।ओपनसीवी: ओपनजीएल मॉडलव्यू मैट्रिक्स

solvePnP के लिए documentation कहना है कि यह एक रोटेशन वेक्टर आउटपुट "है कि (एक साथ के साथ [अनुवाद वेक्टर]) मॉडल से अंक कैमरे के लिए समन्वय प्रणाली समन्वय प्रणाली लाता है।" मुझे लगता है कि मैं जो चाहता हूं उसके विपरीत है; चूंकि मेरा ट्रैक्टर विमान z = 0 पर है, इसलिए मुझे एक मॉडलव्यू मैट्रिक्स चाहिए जो उस क्वाड को उचित 3 डी प्लेन में बदल देगा।

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

std::vector<Point2f> corners; 
bool found = findChessboardCorners(*_imageBuffer, cv::Size(5,4), corners, 
             CV_CALIB_CB_FILTER_QUADS | 
             CV_CALIB_CB_FAST_CHECK); 
if(found) 
{ 
    drawChessboardCorners(*_imageBuffer, cv::Size(6, 5), corners, found); 

    std::vector<double> distortionCoefficients(5); // camera distortion 
    distortionCoefficients[0] = 0.070969; 
    distortionCoefficients[1] = 0.777647; 
    distortionCoefficients[2] = -0.009131; 
    distortionCoefficients[3] = -0.013867; 
    distortionCoefficients[4] = -5.141519; 

    // Since the image was resized, we need to scale the found corner points 
    float sw = _width/SMALL_WIDTH; 
    float sh = _height/SMALL_HEIGHT; 
    std::vector<Point2f> board_verts; 
    board_verts.push_back(Point2f(corners[0].x * sw, corners[0].y * sh)); 
    board_verts.push_back(Point2f(corners[15].x * sw, corners[15].y * sh)); 
    board_verts.push_back(Point2f(corners[19].x * sw, corners[19].y * sh)); 
    board_verts.push_back(Point2f(corners[4].x * sw, corners[4].y * sh)); 
    Mat boardMat(board_verts); 

    std::vector<Point3f> square_verts; 
    square_verts.push_back(Point3f(-1, 1, 0));        
    square_verts.push_back(Point3f(-1, -1, 0)); 
    square_verts.push_back(Point3f(1, -1, 0)); 
    square_verts.push_back(Point3f(1, 1, 0)); 
    Mat squareMat(square_verts); 

    // Transform the camera's intrinsic parameters into an OpenGL camera matrix 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    // Camera parameters 
    double f_x = 786.42938232; // Focal length in x axis 
    double f_y = 786.42938232; // Focal length in y axis (usually the same?) 
    double c_x = 217.01358032; // Camera primary point x 
    double c_y = 311.25384521; // Camera primary point y 


    cv::Mat cameraMatrix(3,3,CV_32FC1); 
    cameraMatrix.at<float>(0,0) = f_x; 
    cameraMatrix.at<float>(0,1) = 0.0; 
    cameraMatrix.at<float>(0,2) = c_x; 
    cameraMatrix.at<float>(1,0) = 0.0; 
    cameraMatrix.at<float>(1,1) = f_y; 
    cameraMatrix.at<float>(1,2) = c_y; 
    cameraMatrix.at<float>(2,0) = 0.0; 
    cameraMatrix.at<float>(2,1) = 0.0; 
    cameraMatrix.at<float>(2,2) = 1.0; 

    Mat rvec(3, 1, CV_32F), tvec(3, 1, CV_32F); 
    solvePnP(squareMat, boardMat, cameraMatrix, distortionCoefficients, 
       rvec, tvec); 

    _rv[0] = rvec.at<double>(0, 0); 
    _rv[1] = rvec.at<double>(1, 0); 
    _rv[2] = rvec.at<double>(2, 0); 
    _tv[0] = tvec.at<double>(0, 0); 
    _tv[1] = tvec.at<double>(1, 0); 
    _tv[2] = tvec.at<double>(2, 0); 
} 

ड्राइंग कोड में फिर ...

GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f); 
modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, -tv[1], -tv[0], -tv[2]); 
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, -rv[0], 1.0f, 0.0f, 0.0f); 
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, -rv[1], 0.0f, 1.0f, 0.0f); 
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, -rv[2], 0.0f, 0.0f, 1.0f); 

कोने मैं (यानी से मूल के आसपास इकाई लंबाई की एक घन बनाने के प्रतिपादन कर रहा हूँ - प्रत्येक किनारे के साथ 0.5 से 0.5।) मुझे पता है कि ओपनजीएल अनुवाद कार्यों में "रिवर्स ऑर्डर" में परिवर्तन किए गए हैं, इसलिए उपरोक्त को ज़ेड, वाई, और फिर एक्स अक्ष के साथ घन घुमाया जाना चाहिए, और फिर इसका अनुवाद करना चाहिए। हालांकि, ऐसा लगता है कि इसका अनुवाद पहले किया जा रहा है और फिर घुमाया गया है, तो शायद ऐप्पल का GLKMatrix4 अलग-अलग काम करता है?

This question मेरा बहुत ही समान लगता है, और विशेष रूप से कोडर 9 का उत्तर ऐसा लगता है कि मैं जो कुछ भी ढूंढ रहा हूं वह उतना ही कम हो सकता है। हालांकि, मैंने कोशिश की और परिणामों को मेरी विधि से तुलना की, और मैट्रिस जो मैं दोनों मामलों में पहुंचा था वही थे। मुझे लगता है कि यह जवाब सही है, लेकिन मुझे कुछ महत्वपूर्ण जानकारी याद आ रही है।

+1

यह करने का प्रयास करें कि यह कैसे करें। समन्वय प्रणाली मतभेद के विषय पर इस पोस्ट को देखा। http://stackoverflow.com/questions/9081900/reference-coordinate-system-changes-between-opencv-opengl-and-android-sensor – Koobz

उत्तर

2

आपको यह सुनिश्चित करना होगा कि धुरी सही दिशा का सामना कर रहे हैं। एक्स-वाई-जेड आधार प्रत्यक्ष है यह सुनिश्चित करने के लिए विशेष रूप से, वाई और जेड अक्ष ओपनजीएल और ओपनसीवी में विभिन्न दिशाओं का सामना कर रहे हैं। आप इस blog post में कुछ जानकारी और कोड (एक आईपैड कैमरा के साथ) पा सकते हैं।

- संपादित करें - आह ठीक है। दुर्भाग्यवश, मैंने इन संसाधनों का उपयोग कुछ एल्गोरिदम का परीक्षण करने के लिए इसे दूसरे तरीके से गोल करने के लिए किया था (opengl ---> opencv)। मेरा मुख्य मुद्दा यह था कि छवियों का पंक्ति क्रम ओपनजीएल और ओपनसीवी (शायद यह मदद करता है) के बीच उलटा हुआ था।

कैमरे को अनुकरण करते समय, मैं उसी प्रोजेक्शन मैट्रिस में आया जो here और generalized projection matrix paper में पाया जा सकता है। ब्लॉग पोस्ट की टिप्पणियों में उद्धृत This paper कंप्यूटर दृष्टि और ओपनजीएल अनुमानों के बीच कुछ लिंक भी दिखाता है।

+0

लिंक के लिए धन्यवाद। दुर्भाग्य से मैंने पहले उस पोस्ट को देखा है। मैंने अपने कोड का उपयोग कम या कम वर्बैटिम का उपयोग करने की कोशिश की, और मूल रूप से एक ही परिणाम मिला। मुझे लगता है कि पोस्ट में भी महत्वपूर्ण विवरण गुम हैं क्योंकि यह दिखाता है कि वह होमोग्राफी की गणना कैसे करता है, जो शायद महत्वपूर्ण है। मैं वाई/जेड अक्ष मतभेदों के बारे में भी जागरूक था, लेकिन मैं कई बार अपने कोड पर गया हूं और जहां तक ​​मैं कह सकता हूं कि मैं इसे संभालने में सक्षम हूं। –

0

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

कोनों के वेक्टर में बिंदु छवि के ऊपरी बाएं कोने में मूल (0,0) है और वाई धुरी छवि के नीचे की ओर है।गणित से अक्सर हम केंद्र के मूल के साथ समन्वय प्रणाली के बारे में सोचते हैं और वाई अक्ष को छवि के शीर्ष की ओर ले जाते हैं। निर्देशांक से आप बोर्ड_वर्क्स में धक्का दे रहे हैं, मुझे लगता है कि आप एक ही गलती कर रहे हैं। अगर ऐसी बात है, यह कुछ इस तरह से कोनों के पदों को बदलने के लिए आसान है:

for (i=0;i<corners.size();i++) { 
    corners[i].x -= width/2; 
    corners[i].y = -corners[i].y + height/2; 
} 

तो आप() solvePnP कहते हैं। इसे डिबग करना मुश्किल नहीं है, बस चार कोनों और अनुमानित आर और टी की स्थिति मुद्रित करें, और देखें कि क्या वे समझ में हैं। फिर आप OpenGL चरण पर जा सकते हैं। कृपया मुझे बतायेँ कि यह कैसा चलेगा।

संबंधित मुद्दे