2012-03-20 29 views
9

की एक पंक्ति को परिवर्तित करना मेरे पास एक साधारण सरल सवाल है: cv::Mat की एक पंक्ति कैसे लें और std::vector में सभी डेटा प्राप्त करें? cv::Mat में doubles है (यह प्रश्न के उद्देश्य के लिए कोई आसान डेटाटाइप हो सकता है)।सीवी :: मैट से std :: vector

ओपनसीवी दस्तावेज के माध्यम से जाना बहुत ही भ्रमित है, जब तक कि मैं पृष्ठ को बुकमार्क नहीं करता हूं, मुझे गुगलिंग द्वारा दो बार एक प्रलेखन पृष्ठ नहीं मिल रहा है, इसमें बहुत कुछ है और नेविगेट करना आसान नहीं है।

मैट्रिक्स तत्व तक पहुंचने के लिए मुझे cv::Mat::at(..) मिला है, लेकिन मुझे C OpenCV से याद है कि तत्वों तक पहुंचने के कम से कम 3 अलग-अलग तरीके थे, उनमें से सभी अलग-अलग उद्देश्यों के लिए उपयोग किए गए थे ... याद नहीं किया जा सकता था कि किसके लिए उपयोग किया गया था/

तो, जबकि मैट्रिक्स तत्व-दर-तत्व काम निश्चित रूप से होगा कॉपी करने, मैं एक तरीका है कि अधिक कुशल और यदि संभव हो तो एक से, में थोड़ा और अधिक सुरुचिपूर्ण पाश के लिए के लिए देख रहा हूँ: जो हर एक पंक्ति। here पर

+0

मुझे लगता है कि एक डुप्लीकेट सवाल: एच ttp: //stackoverflow.com/questions/5405070/cvmat-to-stdvector-conversion – piokuc

+0

@piokuc मैंने इसे देखा, लेकिन यह ओपनसीवी 2.0 (आज से पुराना संस्करण) * और * संबंधित के लिए प्लेटफार्म विशिष्ट (विजुअल स्टूडियो) था एक विशिष्ट 'सीवी :: मैट 'रैपर' सीवी :: Mat_' – penelope

उत्तर

16

ओपनसीवी मैट्रिस में डेटा पंक्ति-प्रमुख क्रम में रखा गया है, ताकि प्रत्येक पंक्ति को संगत होने की गारंटी दी जा सके। इसका मतलब है कि आप एक पंक्ति में डेटा को सादा सी सरणी के रूप में समझ सकते हैं। निम्न उदाहरण the documentation से सीधे आता है:

// compute sum of positive matrix elements 
// (assuming that M is double-precision matrix) 
double sum=0; 
for(int i = 0; i < M.rows; i++) 
{ 
    const double* Mi = M.ptr<double>(i); 
    for(int j = 0; j < M.cols; j++) 
     sum += std::max(Mi[j], 0.); 
} 

इसलिए सबसे कारगर तरीका std::vector को सादा सूचक पारित करने के लिए है:

// Pointer to the i-th row 
const double* p = mat.ptr<double>(i); 

// Copy data to a vector. Note that (p + mat.cols) points to the 
// end of the row. 
std::vector<double> vec(p, p + mat.cols); 

यह निश्चित रूप iterators begin() और end() द्वारा लौटाए का उपयोग कर की तुलना में तेजी है, चूंकि पंक्तियों के बीच अंतराल का समर्थन करने के लिए उनमें अतिरिक्त गणना शामिल है।

5

प्रलेखन से, आप cv::Mat::row के माध्यम से एक विशेष पंक्ति प्राप्त कर सकते हैं, जो एक नया cv::Mat, जिस पर आप cv::Mat::begin और cv::Mat::end साथ iterator कर सकते हैं वापस आ जाएगी। जैसे, निम्नलिखित काम करना चाहिए:

cv::Mat m/*= initialize */; 
// ... do whatever... 
cv::Mat first_row(m.row(0)); 
std::vector<double> v(first_row.begin<double>(), first_row.end<double>()); 

ध्यान दें कि मैं किसी भी OpenCV पता नहीं है, लेकिन googling "OpenCV चटाई" बुनियादी प्रकार प्रलेखन के लिए सीधे नेतृत्व किया और उस के अनुसार, इस ठीक काम करना चाहिए।

मैट्रिक्स इटरेटर यादृच्छिक-पहुंच इटरेटर्स हैं, इसलिए उन्हें किसी भी एसटीएल एल्गोरिदम में पारित किया जा सकता है, जिसमें std :: sort() शामिल है।

यह documentiation से भी है, तो आप वास्तव में एक प्रति के बिना यह कर सकता है:

cv::Mat m/*= initialize */; 
// ... do whatever... 
// first row   begin    end 
std::vector<double> v(m.begin<double>(), m.begin<double>() + m.size().width); 

पहली पंक्ति की तुलना में अधिक उपयोग करने के लिए, मैं, पहले टुकड़ा की सलाह देते हैं, क्योंकि यह हो जाएगा उस तरह के बहुत साफ और कोई भारी प्रतिलिपि प्रतीत नहीं होती है क्योंकि डेटा प्रकारों को संदर्भ-गणना माना जाता है।

+0

क्या आपका मतलब आपके दूसरे उदाहरण में 'm.size() चौड़ाई' था? ध्यान दें कि OpenCV matrices पंक्ति-प्रमुख संग्रहीत किए जाते हैं और आप * पंक्तियों * की संख्या जोड़ रहे हैं जब आपको शायद * कॉलम * की संख्या जोड़नी चाहिए। –

+0

@ फ़र्डिनेंड: वूप्स, हां, यह वास्तव में मेरा इरादा था। संकेत के लिए धन्यवाद। – Xeo

+1

'm.size() चौड़ाई' के बजाय, आप सीधे 'm.cols' का उपयोग कर सकते हैं। –

29

यह रूप में सरल रूप में किया जाना चाहिए:

m.row(row_idx).copyTo(v); 

कहाँ mcv::Mat है CV_64F गहराई और v होने std::vector<double>

+0

वाह यह बहुत अच्छा है। लेकिन, चूंकि मुझे वास्तव में एक नया वेक्टर बनाने और डेटा के साथ भरने की ज़रूरत है, मुझे लगता है कि वेक्टर कन्स्ट्रक्टर को पॉइंटर्स देने से इस मामले में बेहतर काम होगा। – penelope

2

तुम भी cv::Rect

m(cv::Rect(0, 0, 1, m.cols)) 

उपयोग कर सकते हैं आप पहली पंक्ति दे देंगे ।

matrix(cv::Rect(x0, y0, len_x, len_y); 

मतलब है कि आप matrix से sub_matrix मिल जाएगा जिसका ऊपरी बाएँ कोने (x0,y0) है और आकार (len_x, len_y) है। (row,col)

+2

यह 'एम होना चाहिए (सीवी :: रेक्ट (0, 0, m.cols, 1)) ',' 1, m.cols' नहीं। – zhangxaochen

0

मैं इस काम करता है लगता है,

एक उदाहरण:

Mat Input(480, 720, CV_64F, Scalar(100)); 

मैट्रिक्स के 1 पंक्ति फसल:

Rect roi(Point(0, 0), Size(720, 1)); 

तो:

std::vector<std::vector<double> > vector_of_rows; 

vector_of_rows.push_back(Input(roi)); 
संबंधित मुद्दे