सवाल छवियों के साथ ओपनसीवी और एसवीएम का उपयोग करना


मुझे एक छवि पढ़ने, प्रशिक्षण के लिए सुविधाओं को निकालने, और एसवीएम का उपयोग कर ओपनसीवी में नई छवियों पर परीक्षण करने में कठिनाई हो रही है। क्या कोई मुझे एक महान लिंक पर इंगित कर सकता है? मैंने देखा है वेक्टर मशीनों का समर्थन करने के लिए ओपनसीवी परिचय। लेकिन यह छवियों में पढ़ने में मदद नहीं करता है, और मुझे यकीन नहीं है कि इसे कैसे शामिल किया जाए।


मेरे लक्ष्य एक छवि में पिक्सेल वर्गीकृत करना है। ये पिक्सेल एक वक्र से संबंधित होगा। मैं प्रशिक्षण मैट्रिक्स बनाने में समझता हूं (उदाहरण के लिए, छवि ए 1,1 1,2 1,3 1,4 1,5 2,1 2,2 2,3 2,4 2,5 3,1 3,2 3,3 3,4 3,5

मैं अपने प्रशिक्षण मैट्रिक्स को [3] [2] = {{1,1} {1,2} {1,3} {1,4} {1,5} {2,1} ..} के रूप में बनाउंगा। }

हालांकि, मैं लेबल के बारे में थोड़ा उलझन में हूँ। मेरी समझ से, मुझे यह निर्दिष्ट करना होगा कि प्रशिक्षण मैट्रिक्स में कौन सी पंक्ति (छवि) मेल खाती है, जो एक वक्र या गैर-वक्र से मेल खाती है। लेकिन, अगर मैं वक्र से संबंधित कुछ पिक्सेल और कुछ वक्र से संबंधित नहीं हैं तो मैं प्रशिक्षण मैट्रिक्स पंक्ति (छवि) को कैसे लेबल कर सकता हूं। उदाहरण के लिए, मेरा प्रशिक्षण मैट्रिक्स [3] [2] = {{1,1} {1,2} {1,3} {1,4} {1,5} {2,1} .. {}} है , पिक्सल {1,1} और {1,4} वक्र से संबंधित हैं लेकिन शेष नहीं है।


58
2018-02-04 20:15


मूल


ओपनसीवी 3.x में, एसवीएम एक्सेस प्रक्रियाएं थोड़ा अलग हैं। उन लोगों की तलाश करने वाले लोगों के लिए, stackoverflow.com/questions/27114065/opencv-3-svm-training , यह लिंक @ वाल्फी के उत्तर का पालन करने के लिए उचित वाक्यविन्यास प्रदान करेगा। - Saksham Sharma


जवाब:


मुझे हाल ही में इसका सामना करना पड़ा है, और यहां मैं छवियों के लिए काम करने के लिए एसवीएम प्राप्त करने के लिए क्या कर रहा हूं।

छवियों के एक सेट पर अपने एसवीएम को प्रशिक्षित करने के लिए, पहले आपको SVM के लिए प्रशिक्षण मैट्रिक्स बनाना होगा। इस मैट्रिक्स को निम्नानुसार निर्दिष्ट किया गया है: मैट्रिक्स की प्रत्येक पंक्ति एक छवि से मेल खाती है, और उस पंक्ति में प्रत्येक तत्व वर्ग की एक विशेषता से मेल खाता है - इस मामले में, पिक्सेल का एक निश्चित बिंदु पर रंग। चूंकि आपकी छवियां 2 डी हैं, इसलिए आपको उन्हें 1 डी मैट्रिक्स में परिवर्तित करने की आवश्यकता होगी। प्रत्येक पंक्ति की लंबाई छवियों का क्षेत्र होगा (ध्यान दें कि छवियों को एक ही आकार होना चाहिए)।

मान लीजिए कि आप 5 अलग-अलग छवियों पर एसवीएम को प्रशिक्षित करना चाहते थे, और प्रत्येक छवि 4x3 पिक्सेल थी। सबसे पहले आपको प्रशिक्षण मैट्रिक्स को प्रारंभ करना होगा। मैट्रिक्स में पंक्तियों की संख्या 5 होगी, और स्तंभों की संख्या छवि का क्षेत्र होगा, 4 * 3 = 12।

int num_files = 5;
int img_area = 4*3;
Mat training_mat(num_files,img_area,CV_32FC1);

आदर्श रूप में, num_files तथा img_area हार्डकोड नहीं किया जाएगा, लेकिन एक निर्देशिका के माध्यम से लूपिंग और छवियों की संख्या गिनने और छवि के वास्तविक क्षेत्र को लेने से प्राप्त किया जाएगा।

अगला कदम पंक्तियों को "भरना" है training_mat प्रत्येक छवि से डेटा के साथ। नीचे एक उदाहरण है कि यह मानचित्रण एक पंक्ति के लिए कैसे काम करेगा।

Convert 2D image matrix to 1D matrix

मैंने छवि मैट्रिक्स के प्रत्येक तत्व को क्रमांकित किया है जहां इसे प्रशिक्षण मैट्रिक्स में संबंधित पंक्ति में जाना चाहिए। उदाहरण के लिए, यदि वह तीसरी छवि थी, तो प्रशिक्षण मैट्रिक्स में यह तीसरी पंक्ति होगी।

आपको प्रत्येक छवि के माध्यम से लूप करना होगा और तदनुसार आउटपुट मैट्रिक्स में मान सेट करना होगा। एकाधिक छवियों के लिए यहां एक उदाहरण दिया गया है:

Training matrix with multiple images

कोड में आप यह कैसे करेंगे, आप इसका उपयोग कर सकते हैं reshape(), लेकिन मैट्रिस के निरंतर नहीं होने के कारण मुझे इसके साथ समस्याएं थीं। मेरे अनुभव में मैंने ऐसा कुछ किया है:

Mat img_mat = imread(imgname,0); // I used 0 for greyscale
int ii = 0; // Current column in training_mat
for (int i = 0; i<img_mat.rows; i++) {
    for (int j = 0; j < img_mat.cols; j++) {
        training_mat.at<float>(file_num,ii++) = img_mat.at<uchar>(i,j);
    }
}

प्रत्येक प्रशिक्षण छवि के लिए ऐसा करें (वृद्धि को याद रखना file_num)। इसके बाद, आपको अपने प्रशिक्षण मैट्रिक्स को SVM फ़ंक्शन में पास करने के लिए ठीक से सेट अप करना चाहिए। शेष चरणों को ऑनलाइन उदाहरणों के समान होना चाहिए।

ध्यान दें कि ऐसा करने के दौरान, आपको प्रत्येक प्रशिक्षण छवि के लिए लेबल सेट अप करना होगा। तो उदाहरण के लिए यदि आप छवियों के आधार पर आंखों और गैर-आंखों को वर्गीकृत कर रहे थे, तो आपको यह निर्दिष्ट करना होगा कि प्रशिक्षण मैट्रिक्स में कौन सी पंक्ति आंखों और नॉन-आंख से मेल खाती है। इसे 1 डी मैट्रिक्स के रूप में निर्दिष्ट किया गया है, जहां 1 डी मैट्रिक्स में प्रत्येक तत्व 2 डी मैट्रिक्स में प्रत्येक पंक्ति से मेल खाता है। प्रत्येक वर्ग के लिए मान चुनें (उदा।, गैर-आंखों के लिए -1 और आंखों के लिए 1) और उन्हें लेबल मैट्रिक्स में सेट करें।

Mat labels(num_files,1,CV_32FC1);

तो अगर इसमें तीसरा तत्व है labels मैट्रिक्स -1 थे, इसका मतलब है कि प्रशिक्षण मैट्रिक्स में तीसरी पंक्ति "गैर-आंख" वर्ग में है। आप इन मानों को लूप में सेट कर सकते हैं जहां आप प्रत्येक छवि का मूल्यांकन करते हैं। एक चीज जो आप कर सकते हैं वह प्रशिक्षण डेटा को प्रत्येक वर्ग के लिए अलग-अलग निर्देशिकाओं में क्रमबद्ध करना है, और प्रत्येक निर्देशिका में छवियों के माध्यम से लूप, और निर्देशिका के आधार पर लेबल सेट करना है।

करने के लिए अगली बात आपके एसवीएम पैरामीटर सेट अप है। ये मान आपकी परियोजना के आधार पर अलग-अलग होंगे, लेकिन मूल रूप से आप एक घोषित करेंगे CvSVMParams ऑब्जेक्ट करें और मान सेट करें:

CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::POLY;
params.gamma = 3;
// ...etc

इन पैरामीटर को सेट करने के तरीके पर ऑनलाइन कई उदाहरण हैं, जैसे कि आपने प्रश्न में पोस्ट किए गए लिंक में।

अगला, आप एक बनाते हैं CvSVM ऑब्जेक्ट करें और इसे अपने डेटा के आधार पर प्रशिक्षित करें!

CvSVM svm;
svm.train(training_mat, labels, Mat(), Mat(), params);

आपके पास कितना डेटा है, इस पर निर्भर करता है कि इसमें काफी समय लग सकता है। प्रशिक्षण के बाद, हालांकि, आप प्रशिक्षित एसवीएम को बचा सकते हैं ताकि आपको हर बार इसे पुनः प्रशिक्षित न करना पड़े।

svm.save("svm_filename"); // saving
svm.load("svm_filename"); // loading

प्रशिक्षित एसवीएम का उपयोग करके अपनी छवियों का परीक्षण करने के लिए, बस एक छवि पढ़ें, इसे 1 डी मैट्रिक्स में परिवर्तित करें, और उसमें पास करें svm.predict():

svm.predict(img_mat_1d);

यह आपके लेबल के रूप में सेट किए गए मूल्य के आधार पर एक मूल्य लौटाएगा (उदाहरण के लिए, -1 या 1, ऊपर मेरी आंख / गैर-आंख उदाहरण के आधार पर)। वैकल्पिक रूप से, यदि आप एक समय में एक से अधिक छवियों का परीक्षण करना चाहते हैं, तो आप एक मैट्रिक्स बना सकते हैं जिसमें पहले से परिभाषित प्रशिक्षण मैट्रिक्स के समान प्रारूप है और इसे तर्क के रूप में पास किया गया है। हालांकि, वापसी मूल्य अलग होगा।

सौभाग्य!


205
2018-02-04 21:53



+1 यहां एसवीएम पर सबसे अच्छे उत्तरों में से एक है। महान! - Sam
बहुत बढ़िया सचमुच! :) - Jompa234
@Walfie आपने मेरी पूरी सप्ताहांत सिरदर्द को एक बड़ी मुस्कुराहट में बदल दिया है: डी - Joaquín L. Robles
@ Wish_2_fly मैट्रिक्स में प्रत्येक पंक्ति एक ही आकार होनी चाहिए, इसलिए उन मामलों में जहां आपकी छवियां अलग-अलग आकार के हों, यह आपके आवेदन पर निर्भर है कि इसे कैसे संभाला जाए। व्यक्तिगत रूप से मुझे लगता है कि अगर मैं उस आकार में फिट नहीं होता तो मैं कुछ निश्चित आकार और अपसमूह / डाउन नमूना चुनता हूं। यह या तो इनपुट छवियों पर या जब आप उन्हें अपने प्रोग्राम में पढ़ रहे हैं तो मैट्रिक्स को पॉप्युलेट करने के लिए किया जा सकता है। - Walfie
हालांकि यह एक बहुत अच्छी व्याख्या है, मुझे यह उल्लेख करना होगा कि आम तौर पर आप पूरी छवियों पर वर्गीकरण नहीं करते हैं बल्कि उन छवियों की विशेषताओं पर वर्गीकरण करते हैं। उदाहरण के लिए: छवियों से HOG निकालें और वर्गीकरण को प्रशिक्षित करने के लिए इसका उपयोग करें। - LandonZeKepitelOfGreytBritn