如何在openCV(java)中调整模板匹配的阈值? [英] How to adjust the threshold for template matching in openCV (java)?

查看:571
本文介绍了如何在openCV(java)中调整模板匹配的阈值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用openCV 3.4.7 Android SDK(java)运行模板匹配. 该代码几乎可以完美运行;当模板匹配时,它将在匹配区域上绘制一个矩形.问题在于,即使没有匹配项,它也会绘制一个随机的矩形.我认为发生这种情况是因为阈值设置不正确.如果是这样,有人可以帮我吗?

I am running template matching using openCV 3.4.7 Android SDK (java). The code work almost perfectly; when the template is match, it draws a rectangle on the matching area. The problem is that even when there is no match, it draws a random rectangle. I think that happens because the threshold is not set correctly. If so, can someone please help me out?

代码如下:

public static void run(String inFile, String templateFile, String outFile,
                    int match_method) {
        Mat img = Imgcodecs.imread(inFile);
        Mat templ = Imgcodecs.imread(templateFile);

        // / Create the result matrix
        int result_cols = img.cols() - templ.cols() + 1;
        int result_rows = img.rows() - templ.rows() + 1;
        Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

        // / Do the Matching and Normalize
        Imgproc.matchTemplate(img, templ, result, match_method);
        Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());

        // / Localizing the best match with minMaxLoc
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);

        Point matchLoc;
        if (match_method == Imgproc.TM_SQDIFF
                || match_method == Imgproc.TM_SQDIFF_NORMED) {
            matchLoc = mmr.minLoc;
        } else {
            matchLoc = mmr.maxLoc;
        }

        // / Show me what you got
        Imgproc.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
                matchLoc.y + templ.rows()), new Scalar(0, 0, 128));

        // Save the visualized detection.
        System.out.println("Writing " + outFile);
        Imgcodecs.imwrite(outFile, img);
}

推荐答案

我编写了一个应用,该应用将对游戏守望先锋进行屏幕截图,并试图告诉每个团队中的谁.使用模板匹配并打开简历. 项目需要遍历结果图像并检查值.

i wrote an app that would take a screenshot of the game overwatch and attempt to tell who is on each team. using template matching and open cv. project need to iterate over the result image and check values.

OpenCVUtils.getPointsFromMatAboveThreshold(result, 0.90f)

OpenCVUtils.getPointsFromMatAboveThreshold(result, 0.90f)

public static void scaleAndCheckAll(String guid){       
    Mat source = imread(IMG_PROC_PATH + guid);  //load the source image
    Mat scaledSrc = new Mat(defaultScreenshotSize, source.type());
    resize(source, scaledSrc, defaultScreenshotSize);
    Mat sourceGrey = new Mat(scaledSrc.size(), CV_8UC1);
    cvtColor(scaledSrc, sourceGrey, COLOR_BGR2GRAY);        

    for (String hero : getCharacters()) {
        Mat template = OpenCVUtils.matFromJar(TEMPLATES_FOLDER + hero + ".png", 0); //load a template
        Size size = new Size(sourceGrey.cols()-template.cols()+1, sourceGrey.rows()-template.rows()+1);
        Mat result = new Mat(size, CV_32FC1);
        matchTemplate(sourceGrey, template, result, TM_CCORR_NORMED);// get results
        Scalar color =  OpenCVUtils.randColor();
        List<Point> points = OpenCVUtils.getPointsFromMatAboveThreshold(result, 
0.90f);
        for (Point point : points) {
            //rectangle(scaledSrc, new Rect(point.x(),point.y(),template.cols(),template.rows()), color, -2, 0, 0);
            putText(scaledSrc, hero, point, FONT_HERSHEY_PLAIN, 2, color);
        }
    }
    String withExt = IMG_PROC_PATH + guid +".png";
    imwrite(withExt,  scaledSrc);
    File noExt = new File(IMG_PROC_PATH + guid);
    File ext = new File(withExt);
    noExt.delete();
    ext.renameTo(noExt);                
}

另一种方法.

public static List<Point> getPointsFromMatAboveThreshold(Mat m, float t){
    List<Point> matches = new ArrayList<Point>();
    FloatIndexer indexer = m.createIndexer();
    for (int y = 0; y < m.rows(); y++) {
        for (int x = 0; x < m.cols(); x++) {
            if (indexer.get(y,x)>t) {
                System.out.println("(" + x + "," + y +") = "+ indexer.get(y,x));
                matches.add(new Point(x, y));                   
            }
        }           
    }       
    return matches;
}

您可以从列表中获得第一个,或者如果您希望有多个匹配项,请查看它们之间的距离.

you can just get the first from the list or see how close they are if you expect multiple matches.

这篇关于如何在openCV(java)中调整模板匹配的阈值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆