在照片中寻找美国国旗?

为了纪念7月4日,我有兴趣找到一种在图片中发现美国国旗的程序化方法。 有一个关于在图像中寻找可口可乐罐头的早期流行问题,描述了许多针对该问题的优秀技术,但我不确定它们是否适用于标志,因为

  • 旗帜在风中飘动,因此可能会遮挡自己或以其他方式非线性变形(这使得SIFT等技术难以使用),以及
  • 与可口可乐罐不同,美国国旗的星条旗不是美国国旗的独特之处,可能是利比里亚国旗的一部分,排除了许多“线路签名”技术。
  • 是否有任何标准的图像处理或识别技术特别适合这项任务?


    我的方法概括了这个问题,并且实际上在蓝色区域附近寻找红色和白色条纹(水平或垂直)。 因此它适用于只有美国国旗才有这种模式的场景。

    我的方法是用Java开发的,并使用Marvin Framework。

    算法:

  • 彩色滤光片仅保留与美国国旗相同颜色的像素。
  • 找到水平的红色和白色条纹图案
  • 找到垂直的红色和白色条纹图案
  • 去除小面积图案(噪点)
  • 检查此图案是否被蓝色区域包围
  • 分割区域。
  • 输入:

    在这里输入图像描述

    彩色滤光片:

    旗:

    在这里输入图像描述

    更有趣的是在有很多标志的情况下的表现。

    输入

    在这里输入图像描述

    彩色滤光片:

    在这里输入图像描述

    模式匹配:

    旗:

    在这里输入图像描述

    源代码:

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

    其他结果:

    在这里输入图像描述

    在这里输入图像描述

    在这里输入图像描述


    您可以通过OpenCV库使用“模板匹配”。

    这是方法背后的理论:

    模板匹配是一种在较大图像中搜索和查找模板图像位置的方法。 OpenCV为此提供了函数cv2.matchTemplate()。 它只是将模板图​​像滑过输入图像(如2D卷积),并比较模板图像下的输入图像的模板和补丁。

    代码示例和实现说明可以在这里找到:http://docs.opencv.org/master/d4/dc6/tutorial_py_template_matching.html#gsc.tab=0

    链接地址: http://www.djcxy.com/p/79571.html

    上一篇: Finding the American flag in a picture?

    下一篇: Detecting an object (words) in an image