2016-07-04 5 views
24

चौथे जुलाई के सम्मान में, मुझे एक तस्वीर में अमेरिकी ध्वज का पता लगाने के लिए एक प्रोग्रामेटिक तरीका खोजने में दिलचस्पी थी। वहाँ, एक earlier and popular question about finding Coca-Cola cans in images कि है कि समस्या के लिए अच्छा कई तकनीकों का वर्णन करता है, हालांकि मुझे यकीन है कि वे झंडे क्योंकिएक तस्वीर में अमेरिकी ध्वज ढूँढना?

  1. झंडे हवा में स्पंदन के लिए काम करेंगे नहीं कर रहा हूँ और इसलिए खुद को ढंक लेते हैं या अन्यथा nonlinearly ख़राब (हो सकता है जो एसआईएफटी जैसी तकनीकों का उपयोग करने में थोड़ा कठिन बनाता है), और
  2. कोका कोला के विपरीत, अमेरिकी ध्वज के सितारे और स्ट्रिप्स अमेरिकी ध्वज के लिए अद्वितीय नहीं हैं और कह सकते हैं, flag of Liberia, कई लोगों का निर्णय "रेखा हस्ताक्षर" तकनीकें।

क्या कोई मानक छवि प्रसंस्करण या मान्यता तकनीक है जो इस कार्य के लिए विशेष रूप से उपयुक्त होगी?

+3

आप प्रशिक्षण के लिए एक बड़ी डाटासेट है, के लिए खोज। हाल के वर्षों में इस मोर्चे पर बहुत प्रगति हुई है। – Photon

+1

मुझे पता है कि आप एसओ के एक प्रसिद्ध सदस्य हैं, लेकिन ऐसा लगता है 1) कोई प्रयास नहीं दिया गया था। 2) सवाल बहुत व्यापक है। –

+0

@ सल्वाडोरदाली, दोस्त ने नीचे अपने प्रश्न का उत्तर दिया। अच्छा जवाब भी (मैंने इसे 16 वें अपवॉट बना दिया)। मुझे लगता है कि पूछताछ हालांकि अधिक उत्तरों/दृष्टिकोण के लिए खुला है। –

उत्तर

33

मेरा दृष्टिकोण समस्या को सामान्य करता है और वास्तव में एक नीले क्षेत्र के पास एक लाल और सफेद स्ट्रिप्स पैटर्न (क्षैतिज या लंबवत) की तलाश करता है। इसलिए यह दृश्यों के लिए काम करता है कि केवल अमेरिकी ध्वज में यह पैटर्न है।

मेरा दृष्टिकोण जावा में विकसित किया गया है और Marvin Framework का उपयोग करता है।

एल्गोरिथ्म: अमेरिकी ध्वज के एक ही रंग के साथ ही पिक्सल रखने के लिए

  1. रंग फिल्टर।
  2. क्षैतिज लाल और सफेद स्ट्रिप्स पैटर्न
  3. खोजें खड़ी लाल और सफेद स्ट्रिप्स पैटर्न
  4. छोटे से क्षेत्र (शोर)
  5. चेक इस पैटर्न एक नीले क्षेत्र
  6. सेगमेंट क्षेत्र से घिरा हुआ है कि क्या के साथ पैटर्न निकालें का पता लगाएं ।

इनपुट:

enter image description here

रंग फ़िल्टर:

enter image description here

करें:

enter image description here

अधिक दिलचस्प है इस मामले में प्रदर्शन कई झंडे हैं।

इनपुट:

enter image description here

रंग फ़िल्टर:

enter image description here

पैटर्न मिलान:

enter image description here

करें:

enter image description here

स्रोत कोड:

import static marvin.MarvinPluginCollection.*; 

public class AmericanFlag { 

    public AmericanFlag(){ 
     process("./res/flags/", "flag_0", Color.yellow); 
     process("./res/flags/", "flag_1", Color.yellow); 
     process("./res/flags/", "flag_2", Color.yellow); 
     process("./res/flags/", "flag_3", Color.yellow); 
     process("./res/flags/", "flag_4", Color.blue); 
    } 

    private void process(String dir, String fileName, Color color){ 
     MarvinImage originalImage = MarvinImageIO.loadImage(dir+fileName+".jpg"); 
     MarvinImage image = originalImage.clone(); 
     colorFilter(image); 
     MarvinImageIO.saveImage(image, dir+fileName+"_color.png"); 

     MarvinImage output = new MarvinImage(image.getWidth(), image.getHeight()); 
     output.clear(0xFFFFFFFF); 
     findStripsH(image, output); 
     findStripsV(image, output); 
     MarvinImageIO.saveImage(output, dir+fileName+"_1.png"); 

     MarvinImage bin = MarvinColorModelConverter.rgbToBinary(output, 127); 
     morphologicalErosion(bin.clone(), bin, MarvinMath.getTrueMatrix(5, 5)); 
     morphologicalDilation(bin.clone(), bin, MarvinMath.getTrueMatrix(15, 15)); 
     MarvinImageIO.saveImage(bin, dir+fileName+"_2.png"); 

     int[] centroid = getCentroid(bin); 
     image.fillRect(centroid[0], centroid[1], 30, 30, Color.yellow); 

     int area = getMass(bin); 
     boolean blueNeighbors = hasBlueNeighbors(image, bin, centroid[0], centroid[1], area); 

     if(blueNeighbors){ 
      int[] seg = getSegment(bin); 
      for(int i=0; i<4; i++){ 
       originalImage.drawRect(seg[0]+i, seg[1]+i, seg[2]-seg[0], seg[3]-seg[1], color); 
      } 
      MarvinImageIO.saveImage(originalImage, dir+fileName+"_final.png"); 
     } 
    } 

    private boolean hasBlueNeighbors(MarvinImage image, MarvinImage bin, int centerX, int centerY, int area){ 
     int totalBlue=0; 
     int r,g,b; 
     int maxDistance = (int)(Math.sqrt(area)*1.2); 
     for(int y=0; y<image.getHeight(); y++){ 
      for(int x=0; x<image.getWidth(); x++){ 
       r = image.getIntComponent0(x, y); 
       g = image.getIntComponent1(x, y); 
       b = image.getIntComponent2(x, y); 

       if(
        (b == 255 && r == 0 && g == 0) && 
        (MarvinMath.euclideanDistance(x, y, centerX, centerY) < maxDistance) 
       ){ 
        totalBlue++; 
        bin.setBinaryColor(x, y, true); 
       } 
      } 
     } 

     if(totalBlue > area/5){ 
      return true; 
     } 
     return false; 
    } 

    private int[] getCentroid(MarvinImage bin){ 
     long totalX=0, totalY=0, totalPixels=0; 
     for(int y=0; y<bin.getHeight(); y++){ 
      for(int x=0; x<bin.getWidth(); x++){ 

       if(bin.getBinaryColor(x, y)){ 
        totalX += x; 
        totalY += y; 
        totalPixels++; 
       } 
      } 
     } 

     totalPixels = Math.max(1, totalPixels); 
     return new int[]{(int)(totalX/totalPixels), (int)(totalY/totalPixels)}; 
    } 

    private int getMass(MarvinImage bin){ 
     int totalPixels=0; 
     for(int y=0; y<bin.getHeight(); y++){ 
      for(int x=0; x<bin.getWidth(); x++){ 
       if(bin.getBinaryColor(x, y)){ 
        totalPixels++; 
       } 
      } 
     } 

     return totalPixels; 
    } 

    private int[] getSegment(MarvinImage bin){ 
     int x1=-1, x2=-1, y1=-1, y2=-1; 
     for(int y=0; y<bin.getHeight(); y++){ 
      for(int x=0; x<bin.getWidth(); x++){ 
       if(bin.getBinaryColor(x, y)){ 

        if(x1 == -1 || x < x1){ x1 = x; } 
        if(x2 == -1 || x > x2){ x2 = x; } 
        if(y1 == -1 || y < y1){ y1 = y; } 
        if(y2 == -1 || y > y2){ y2 = y; } 
       } 
      } 
     } 
     return new int[]{x1,y1,x2,y2}; 
    } 

    private void findStripsH(MarvinImage imageIn, MarvinImage imageOut){ 

     int strips=0; 
     int totalPixels=0; 
     int r,g,b; 
     int patternStart; 
     boolean cR=true; 
     int patternLength = -1; 
     for(int y=0; y<imageIn.getHeight(); y++){ 
      patternStart = -1; 
      strips = 0; 
      patternLength=-1; 
      for(int x=0; x<imageIn.getWidth(); x++){ 
       r = imageIn.getIntComponent0(x, y); 
       g = imageIn.getIntComponent1(x, y); 
       b = imageIn.getIntComponent2(x, y); 

       if(cR){ 
        if(r == 255 && g == 0 && b == 0){ 
         if(patternStart == -1){ patternStart = x;} 
         totalPixels++; 
        } else{ 
         if(patternLength == -1){ 
          if(totalPixels >=3 && totalPixels <= 100){ 
           patternLength = (int)(totalPixels); 
          } else{ 
           totalPixels=0; patternStart=-1; strips=0; patternLength=-1; 
          } 
         } else{ 
          if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){ 
           strips++; 
           totalPixels=1; 
           cR = false; 
          } else{ 
           totalPixels=0; patternStart=-1; strips=0; patternLength=-1; 
          } 
         } 
        } 
       } 
       else{ 
        if(r == 255 && g == 255 && b == 255){ 
         totalPixels++; 
        } else{ 
         if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){ 
          strips++; 
          totalPixels=1; 
          cR = true; 
         } else{ 
          totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true; 
         } 
        } 
       } 


       if(strips >= 4){ 
        imageOut.fillRect(patternStart, y, x-patternStart, 2, Color.black); 
        totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true; 
       } 
      } 
     } 
    } 

    private void findStripsV(MarvinImage imageIn, MarvinImage imageOut){ 

     int strips=0; 
     int totalPixels=0; 
     int r,g,b; 
     int patternStart; 
     boolean cR=true; 
     int patternLength = -1; 
     for(int x=0; x<imageIn.getWidth(); x++){ 
      patternStart = -1; 
      strips = 0; 
      patternLength=-1; 
      for(int y=0; y<imageIn.getHeight(); y++){ 
       r = imageIn.getIntComponent0(x, y); 
       g = imageIn.getIntComponent1(x, y); 
       b = imageIn.getIntComponent2(x, y); 

       if(cR){ 
        if(r == 255 && g == 0 && b == 0){ 
         if(patternStart == -1){ patternStart = y;} 
         totalPixels++; 
        } else{ 
         if(patternLength == -1){ 
          if(totalPixels >=3 && totalPixels <= 100){ 
           patternLength = (int)(totalPixels); 
          } else{ 
           totalPixels=0; patternStart=-1; strips=0; patternLength=-1; 
          } 
         } else{ 
          if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){ 
           strips++; 
           totalPixels=1; 
           cR = false; 
          } else{ 
           totalPixels=0; patternStart=-1; strips=0; patternLength=-1; 
          } 
         } 
        } 

//     if(maxL != -1 && totalPixels > maxL){ 
//      totalPixels=0; patternStart=-1; strips=0; maxL=-1; 
//     } 
       } 
       else{ 
        if(r == 255 && g == 255 && b == 255){ 
         totalPixels++; 
        } else{ 
         if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){ 
          strips++; 
          totalPixels=1; 
          cR = true; 
         } else{ 
          totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true; 
         } 
        } 

//     if(maxL != -1 && totalPixels > maxL){ 
//      totalPixels=0; patternStart=-1; strips=0; maxL=-1; 
//      cR=true; 
//     } 
       } 


       if(strips >= 4){ 
        imageOut.fillRect(x, patternStart, 2, y-patternStart, Color.black); 
        totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true; 
       } 
      } 
     } 
    } 

    private void colorFilter(MarvinImage image){ 

     int r,g,b; 
     boolean isR, isB; 
     for(int y=0; y<image.getHeight(); y++){ 
      for(int x=0; x<image.getWidth(); x++){ 
       r = image.getIntComponent0(x, y); 
       g = image.getIntComponent1(x, y); 
       b = image.getIntComponent2(x, y); 

       isR = (r > 120 && r > g * 1.3 && r > b * 1.3); 
       isB = (b > 30 && b < 150 && b > r * 1.3 && b > g * 1.3); 

       if(isR){ 
        image.setIntColor(x, y, 255,0,0); 
       } else if(isB){ 
        image.setIntColor(x, y, 0,0,255); 
       } else{ 
        image.setIntColor(x, y, 255,255,255); 
       } 
      } 
     } 
    } 

    public static void main(String[] args) { 
     new AmericanFlag(); 
    } 
} 

अन्य परिणाम:

enter image description here

enter image description here

enter image description here

+1

लेकिन आपने इसे "लाइबेरिया के झंडे" के साथ परीक्षण नहीं किया ... या यह नई चुनौती है? –

+1

अधिकांश उदाहरण प्रतीत होते हैं कि उनके पास एल्गोरिदम द्वारा वर्णित क्षैतिज और न ही ऊर्ध्वाधर पट्टियां हैं - अधिक विकर्ण की तरह। क्या यह आपके एल्गोरिदम के तरीके में एक विसंगति है? क्या आप वास्तव में क्षैतिज या ऊर्ध्वाधर पट्टियों, या किसी अभिविन्यास के लिए विशेष रूप से देख रहे हैं? या आप किसी भी तरह विकर्ण खोजने के लिए क्षैतिज और ऊर्ध्वाधर विलय कर रहे हैं? – pabrams

+1

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

1

आप OpenCV पुस्तकालय के माध्यम से 'खाका मिलान' इस्तेमाल कर सकते हैं।

यहाँ दृष्टिकोण के पीछे सिद्धांत है:

खाका मिलान खोज और एक बड़ी छवि में टेम्पलेट छवि के स्थान को खोजने के लिए एक विधि है। OpenCV इस उद्देश्य के लिए cv2.matchTemplate() फ़ंक्शन के साथ आता है। यह इनपुट छवि (जैसे 2 डी रूपांतरण में) पर टेम्पलेट छवि को बस स्लाइड करता है और टेम्पलेट छवि के नीचे टेम्पलेट और इनपुट छवि के पैच की तुलना करता है।

कोड उदाहरण और कार्यान्वयन विवरण यहां पाया जा सकता: गहरी छवि वर्गीकरण सीखने: http://docs.opencv.org/master/d4/dc6/tutorial_py_template_matching.html#gsc.tab=0

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