OpenCV模板匹配错误的比赛得分/区域

时间:2014-11-27 15:27:25

标签: java image opencv image-processing computer-vision

对于模板匹配我在java中使用TM_CCOEFF_NORMED,直到现在我总是得到非常准确和有意义的结果,但是使用这个特定的模板图像我有错误的匹配分数。模板图像故意不属于输入(源)图像,因此我希望匹配得分较差,最差,但它给了我最好的; " 1.0"并始终在左上角的同一位置找到模板图像。

这是我的模板图片:

enter image description here

带有红色云输入图像的示例输出:(根据程序,绿色突出显示是最佳匹配)

enter image description here

带有黑暗城市输入图像的示例输出:

enter image description here

MinMaxLocResult mmr = Core.minMaxLoc(result);
matchScore = mmr.maxVal;
对于特定的浅绿色模板图像,

matchScore变量始终为1.0,尽管红色和暗图像根本不与绿色相似。我很高兴你的建议和评论有待改进,因为TM_CCOEFF_NORMED始终将第一个搜索到的正方形/矩形与得分1.0最佳匹配,这是不正确的,另一方面我也尝试了TM_CCORR_NORMEDTM_SQDIFF_NORMED他们给出了不同的比赛得分,这很有希望,但仍然TM_CCORR_NORMED给出了良好的匹配分数,这仍然是我的意外。如果有人可以向我解释匹配方法之间的区别,或者给出已经讨论过这些方法的现有页面的链接,我会很高兴,在opencv docs / tutorials上,只有公式可用但没有详细解释。最后,我想知道何时使用哪种匹配方法来获得最佳效果。

以下是一些代码:

    Mat img = Highgui.imread(inFile);
    Mat templ = Highgui.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 
    Imgproc.matchTemplate(img, templ, result, match_method);
    // / Localizing the best match with minMaxLoc
    MinMaxLocResult mmr = Core.minMaxLoc(result);

3 个答案:

答案 0 :(得分:0)

它不起作用,因为当图片以灰度转换时,它们可能看起来很相似。

cv :: minMaxLoc并不适用于这种情况。

您应该使用其他功能,例如特征提取器或边缘检测器,并使用马哈拉诺比斯距离等指标进行比较

答案 1 :(得分:0)

对于SQDIFF和SQDIFF_NORMED,最佳匹配值较低,其余方法的最佳匹配值较高。

建议:在找到最大或最小位置之前规范化结果图像

希望这会有所帮助。

答案 2 :(得分:0)

我有同样的问题。 似乎模板不能是纯色(所有具有相同值的像素)。 如果模板具有相同的值,则结果的分数必须为1(TM_CCOEFF_NORMED)。 也许您可以将模板匹配方法更改为TM_CcorrNormed

MinMaxLocResult mmr = Core.minMaxLoc(result);

无论什么是正确的,这个方法都会给你最好的匹配。所以根据我的经验,我用两个循环来找到结果中的最佳匹配。

int threshold = 0.95; // for TM_CCOEFF_NORMED and TM_CCORR_NORMED
List<Rect> recognizedRects;
List<double> recognizedScores;
for(int i=0;i<result.height;i++) {
    for(int j=0;j<result.width;j++) {
        if(result.data[i,j,0] > threshold) {
            recognizedRects.add(new Rectangle(j,i,template.width,template.height);
            recognizedScores.add(result.data[i,j,0])
        }
    }
}