algorithm एक तस्वीर में अमेरिकी ध्वज ढूँढना?




image-processing computer-vision (2)

चौथे जुलाई के सम्मान में, मुझे एक तस्वीर में अमेरिकी ध्वज का पता लगाने के लिए एक प्रोग्रामेटिक तरीका खोजने में दिलचस्पी थी। छवियों में कोका-कोला डिब्बे खोजने के बारे में एक पहले और लोकप्रिय सवाल है जो उस समस्या के लिए कई अच्छी तकनीकों का वर्णन करता है, हालांकि मुझे यकीन नहीं है कि वे झंडे के लिए काम करेंगे क्योंकि

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

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


आप OpenCV लाइब्रेरी के माध्यम से 'टेम्पलेट मिलान' का उपयोग कर सकते हैं।

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

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

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


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

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

कलन विधि:

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

इनपुट:

रंग फ़िल्टर:

झंडा:

मामले में प्रदर्शन बहुत दिलचस्प है कई झंडे हैं।

इनपुट :

रंग फ़िल्टर:

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

झंडा:

सोर्स कोड:

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();
    }
}

अन्य परिणाम:





computer-vision