2013-06-17 21 views
5

इनपुट छवि का उपयोग करते हुए एक छवि में सफेद पिक्सल के समूहों: enter image description hereका पता लगा रहा openCV

अपेक्षित आउटपुट: enter image description here

मैं तीन (या की कुछ संख्या) बहुभुज फिट करने का इरादा है (इस मामले के लिए, आयत) इस छवि में "बड़े" सफेद ब्लब्स को इंगित करने के लिए। आउटपुट छवि में खींचे गए आयत सफेद क्षेत्रों की मेरी धारणा के अनुसार हैं। मैं उम्मीद नहीं करता कि एल्गोरिदम इन समान बोडिंग क्षेत्रों के साथ आ जाएगा। मेरी इच्छा है कि सफेद पिक्सेल के क्लस्टर के चारों ओर कुछ तंग बहुभुज फिट करें।

मेरा प्रारंभिक समाधान प्रत्येक समोच्च में बिंदुओं के उत्तल ढक्कन को ढूंढकर, इस छवि के लिए समोच्चों को ढूंढने और प्रत्येक समोच्च के चारों ओर एक बंद उत्तल बहुभुज को फ़िट करने में शामिल था।

हालांकि, चूंकि सफेद क्षेत्रों में काले क्षेत्रों के साथ अत्यधिक खंडित होते हैं और किनारों के चारों ओर घूमते हैं, इसलिए cv2.findContours द्वारा लौटाए गए समोच्चों की संख्या बहुत अधिक है (लगभग 500 या उससे अधिक)। इसके कारण, एक उत्तल पतवार फिट करने से सफेद क्षेत्रों के आकार में सुधार नहीं होता है। सफेद क्षेत्र ज्यादातर अपने मूल सार आकार बनाए रखते हैं। मेरा लक्ष्य एक सफेद क्षेत्र के कई छोटे रूपों को एक पूरे समेकित में विलय करना होगा जिस पर मैं एक उत्तल हलचल फिट कर सकता हूं।

मैं इस समस्या को कैसे हल करते हैं? क्या मुझे शुरुआत में समोच्च बिंदुओं पर एक क्लस्टरिंग एल्गोरिदम का उपयोग करना चाहिए जो कि एक-दूसरे के निकट होने वाले समोच्चों को ढूंढने के लिए करते हैं?

+0

http://en.wikipedia.org/wiki/DBSCAN मदद मिल सकती है। पायथन विज्ञान के तहत। डेमो यहाँ http://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html – baci

उत्तर

1

आप एक्स y प्रत्येक सफेद बिंदु और तीन समूहों के लिए सुविधा के रूप में समन्वय का उपयोग करके क्लस्टरिंग kmeans इस्तेमाल कर सकते हैं। फिर परिणामस्वरूप तीन क्लस्टर के उत्तल झुकाव लें। आपको विभिन्न शुरुआती बिंदुओं को आजमा सकते हैं और सर्वोत्तम परिणाम चुन सकते हैं। http://docs.opencv.org/modules/core/doc/clustering.html#kmeans

2

आप पहली बार समोच्च ढूंढने से पहले छवि को फैला सकते हैं। Dilation उज्ज्वल क्षेत्रों को विकसित करने का कारण बनता है। आप इसके बारे में सोच सकते हैं कि आपकी छवि में प्रत्येक मौजूदा सफेद पिक्सेल के चारों ओर सफेद पिक्सेल जोड़ना। इस तरह पड़ोसी उज्ज्वल आकार विलय हो जाते हैं। http://docs.opencv.org/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

तुम भी धुंधला और सीमा कर सकते हैं फिर से देखें, लेकिन धुंधला कलंक की मात्रा पर निर्भर फैलाव की तुलना में बहुत अधिक महंगा हो सकता है।

3

आप पहली जरूरत प्रदर्शन करने के लिए रूपात्मक बंद होने वाले (जो कटाव के बाद फैलाव है) इस छवि पर। व्यक्तिगत घटकों के आकार और आकार को संरक्षित करते समय यह आपकी छवि के सभी छोटे "छेद" को बंद कर देता है। इसके विरोध में, जब क्षरण के बाद क्षरण का पीछा किया जाता है, तो यह छवि में शोर बिंदुओं को हटा देता है। मैं एक समान छवि पर काम कर रहा हूं और मुझे अपने घटकों को बाहर करने के लिए 10 गुना फैलाव + क्षरण करना था। ऐसा करने के बाद, कनेक्टेड घटकों का उपयोग करें या समोच्च खोजें। यह निश्चित रूप से समोच्च संख्या 400 से 20-30 तक नीचे लाएगा।

दूसरे, आप आप 3 समूहों की जरूरत का उल्लेख किया। हालांकि दो छोटे समूहों (लाल रेखा से ढंका) एक में विलय हो सकता था। मैंने इससे क्या किया था कि आप चाहते हैं कि आपका प्रत्येक क्लस्टर जितना संभव हो सके अपने बाध्य आयत में कसकर फिट बैठे। इसलिए, मैं सुझाव देता हूं कि आप थ्रेसहोल्ड दक्षता निर्धारित करें (80% कहें) और प्रत्येक कनेक्टेड घटक को क्लस्टर में मर्ज करने के लिए पदानुक्रमित क्लस्टरिंग का उपयोग करें। अपने सफेद पिक्सल डालती जब (एक समूह से) उनके सीमांकन आयत के अंतरिक्ष के 80% से कम है, तो आप क्लस्टरिंग बंद करो और समूहों मिलेगा।

0

आप अपने आकार के आसपास अनुमानित आकृति आकर्षित कर सकते हैं जब तक आप सभी आवश्यक जुड़े क्षेत्रों मिलता है। इसके साथ मैं छवि को प्रभावी ढंग से मिटा रहा हूं। यदि आप उन जुड़े क्षेत्रों के चारों ओर एक हल खींचते हैं, तो आपको अपने लाल आयताकार मिलते हैं।

बस दोहराते रहें जब तक अपने सबसे बड़े तीन हल्स कुछ आवश्यक संपत्ति है (उदाहरण के लिए यदि वे सभी सफेद डॉट्स के 99% को कवर)

#include <vector> 
using std::vector; 
#include <algorithm> 
using std::sort; 
#include <string> 
using std::string; 
using std::to_string; 
#include <iostream> 
using std::clog; 
using std::endl; 
#include <opencv2/opencv.hpp> 
using namespace cv; 

int main() 
{ 
    typedef vector<Point> Polygon; 
    typedef vector<Polygon> Polygons; 
    Mat mFrame; 
    Mat mOrig; 
    mFrame = imread("R2TsZ.png"); 
    mFrame.copyTo(mOrig); 
    Mat mOrigHull; 
    Mat mOut; 
    int fileCounter = 0; 
    while(true){ 
    clog<< "image read"<< endl; 
    cvtColor(mFrame, mOut, CV_BGR2GRAY); 
    clog<< "image grayscaled"<< endl; 
    Polygons contours; 
    Polygons aContours; 
    Polygons hulls; 
    OutputArray hierarchy = {}; 

    findContours(mOut, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); 
    clog<< contours.size()<< " contours found"<< endl; 
    sort(contours.begin(), contours.end(), [](auto p1, auto p2){ 
     return contourArea(p1) > contourArea(p2); 
    }); 
    clog<< "contours sorted"<< endl; 
    aContours.resize(contours.size()); 
    hulls.resize(contours.size()); 
    for(size_t i = 0; i < aContours.size() - 1; ++ i){ 
     approxPolyDP(contours[i], aContours[i], 20, true); 
     drawContours(mFrame, aContours, i, Scalar(255, 255, 255), 10); 
     convexHull(aContours[i], hulls[i], true); 
    } 
    mOrig.copyTo(mOrigHull); 
    for(size_t i = 0; i < 3; ++ i){ 
     drawContours(mOrigHull, hulls, i, Scalar(0, 0, 255), 10); 
    } 
    imshow("out", mOrigHull); 
    int key = waitKey() & 0xff; 
    if(key == 27){ 
     return EXIT_SUCCESS; 
    } 
    if(key == 'p'){ 
     string file = "test_" + to_string(++ fileCounter) + ".png"; 
     imwrite(file, mOrigHull); 
     clog<< file<< " saved."<< endl; 
    } 
    } 
} 

opencv से इस tutorial में और अधिक देखें।

enter image description here

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