2013-02-09 13 views
20

क्या ओपनसीवी cv::Mat ऑब्जेक्ट को Eigen::Matrix में परिवर्तित करने का एक उलट तरीका है?ओपनसीवी सीवी :: मैट और ईजिन :: मैट्रिक्स

उदाहरण के लिए, कर के कुछ तरीका:

cv::Mat cvMat; 
Eigen::Matrix eigMat; 
camera->retrieve(cvMat); 

// magic to convert cvMat to eigMat 
// work on eigMat 
// convert eigMat back to cvMat 

imshow("Image", cvMat);

मैं cv2eigen और eigen2cv, लेकिन जिसके परिणामस्वरूप cvMat का उपयोग कर की कोशिश की है पूरी तरह से घायल है और मैं वास्तव में यकीन है कि क्यों नहीं कर रहा हूँ। आयाम सही हैं, लेकिन ग्राफिक्स पूरी तरह से ट्रैश किए गए हैं, इसलिए संभवतः एक बाइट-प्रति-पिक्सेल या डेटासाइज़ समस्या?

उत्तर

19

आपको ईजिन एसडीके द्वारा सीधे उपयोग किए जाने के लिए ओपनसीवी मैट्रिस को लपेटने के लिए Eigen :: मानचित्र का उपयोग करने पर विचार करना चाहिए। के लिए

//allocate memory for a 4x4 float matrix 
cv::Mat cvT(4,4,CV_32FC1); 

//directly use the buffer allocated by OpenCV 
Eigen::Map<Matrix4f> eigenT(cvT.data()); 

: यह आपको OpenCV द्वारा आवंटित मैट्रिक्स पर Eigen में लागू लगभग सभी कार्यक्षमताओं

विशेष रूप से आप बस एक Eigen :: मानचित्र सीवी सूचक प्रदान :: चटाई बफर का दृष्टांत लागू करने के लिए अनुमति देता है पर Eigen :: मानचित्र में अधिक जानकारी के Eigen Tutorial: Map Class

+0

बिल्कुल सही, यह वही है जो मैं ढूंढ रहा था। बहु-चैनल छवि (आरजीबी, वाईयूवी, या चैनलों के किसी भी अन्य संयोजन) का उपयोग करते समय, आप इसे सर्वश्रेष्ठ रूप से कैसे परिवर्तित करेंगे? प्रति चैनल एक अलग मैट्रिक्स? WidthXheightXchannels के 3 डी मैट्रिक्स में? या बस चौड़ाई (चौड़ाई * 3) * ऊंचाई से इसे विस्तारित करें? – Yeraze

+8

Mulit-channel छवियों को आम तौर पर इंटरलीव किए गए सरणी (जैसे RGBRGBRGB ...) के रूप में संग्रहीत किया जाता है।आप उनके साथ क्या करना चाहते हैं, इस पर निर्भर करते हुए आप प्रत्येक चैनल को एक अलग ईजेन :: मैप को स्ट्रैड पैरामीटर का शोषण करने पर विचार कर सकते हैं: 'सीवी :: मैट सीवीटी (4,4, सीवी_32 एफसी 3); // एक 3 चैनल फ्लोट मैट्रिक्स Eigen :: मानचित्र > लाल (cvT.data); ईजिन :: मानचित्र > हरा (cvT.data +1); Eigen :: मानचित्र > नीला (cvT.data +2); ' – Pierluigi

+0

cvT.data() का उपयोग करना मेरे लिए काम नहीं करता है, एक कंपाइलर त्रुटि देता है। मैंने जवाब दिया कि मैं इसे नीचे कैसे करता हूं, जिसमें सूचनाएं मनमाने ढंग से आकार के मैट्रिस के लिए और ईजिन से ओपनसीवी के विपरीत रूपांतरण के साथ कैसे करें। – Ela782

41

पर एक नज़र तुम भी उपयोग कर सकते हैं

void eigen2cv(const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst) 
,210

और

void cv2eigen(const Mat& src, Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst) 

#include <opencv2/core/eigen.hpp> से।

18

आप ईजिन और ओपनसीवी (डेटा कॉपी किए बिना) के बीच मनमाने ढंग से मैट्रिक्स मैप कर सकते हैं।

आप दो बातें हालांकि बारे में पता होना करने के लिए है: स्तंभ-प्रमुख भंडारण के लिए

  • Eigen चूक, OpenCV भंडार पंक्ति-प्रमुख। इसलिए, OpenCV डेटा मैप करते समय Eigen :: RowMajor ध्वज का उपयोग करें।

  • ओपनसीवी मैट्रिक्स निरंतर होना चाहिए (यानी ocvMatrix.isContinuous() को सत्य होने की आवश्यकता है)। यह मामला है यदि आप मैट्रिक्स के निर्माण पर मैट्रिक्स के लिए स्टोरेज आवंटित करते हैं (उदाहरण के लिए नीचे दिए गए मेरे उदाहरण में, या यदि मैट्रिक्स मैट डब्ल्यू = ए.in वी() जैसे ऑपरेशन का परिणाम है;)

उदाहरण:

Mat A(20, 20, CV_32FC1); 
cv::randn(A, 0.0f, 1.0f); // random data 

// Map the OpenCV matrix with Eigen: 
Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> A_Eigen(A.ptr<float>(), A.rows, A.cols); 

// Do something with it in Eigen, create e.g. a new Eigen matrix: 
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> B = A_Eigen.inverse(); 

// create an OpenCV Mat header for the Eigen data: 
Mat B_OpenCV(B.rows(), B.cols(), CV_32FC1, B.data()); 

मल्टी चैनल मैट्रिक्स के लिए (जैसे चित्र), तो आप उपयोग कर सकते हैं 'स्ट्राइड' Pierluigi उसकी टिप्पणी में सुझाव बिल्कुल के रूप में!

0

Pierluigi के संस्करण ने पूरी तरह से 3 चैनल छवियों के लिए मेरे लिए काम नहीं किया है! कुछ जांच के बाद मैंने निम्नलिखित समाधान के साथ समाप्त किया जो मेरे लिए काम करता है:

using namespace Eigen; 

constexpr uint32_t height = 3; 
constexpr uint32_t width = 7; 

cv::Mat img(height, width, CV_32FC3, cv::Scalar(1.0f, 2.0f, 3.0f)); 

using MatrixXfRowMajor = Matrix<float, Dynamic, Dynamic, RowMajor>; 
using C3Stride = Stride<Dynamic, 3>; 
C3Stride c3Stride(width *3,3); 


using cvMap = Map<MatrixXfRowMajor, Unaligned, C3Stride >; 
cvMap imgC1(reinterpret_cast<float*>(img.data) + 0, img.rows, img.cols, c3Stride); 
cvMap imgC2(reinterpret_cast<float*>(img.data) + 1, img.rows, img.cols, c3Stride); 
cvMap imgC3(reinterpret_cast<float*>(img.data) + 2, img.rows, img.cols, c3Stride); 

std::cout << imgC1 << std::endl << std::endl; 
std::cout << imgC2 << std::endl << std::endl; 
std::cout << imgC3 << std::endl << std::endl; 
संबंधित मुद्दे