【问题标题】:Template Matching with Mask模板匹配与掩码
【发布时间】:2015-02-01 23:05:58
【问题描述】:

我想使用掩码执行模板匹配。一般来说,通过将图像从空间域转换为频域,可以更快地进行模板匹配。但是,如果我想用面具执行相同的操作,有什么方法可以应用吗?我正在使用opencv c++。 opencv 中是否已经有任何匹配的函数来完成这个任务?

我目前的方法:

  • 带掩码的图像 A 和图像 B 按位异或。

  • 计算非零像素。

  • 用这个计数填充结果矩阵。

  • 搜索 maxi-ma。

我现在猜测的几个参数是:

  • 如果匹配少于 25%,则跳过 Tile 位置。
  • 如果匹配率低于 25%,则跳过平铺位置。

  • 如果前一个 Tile 的匹配率低于 50%,则跳过 Tile 位置。

我的问题:是否有任何算法可以进行这种匹配?有没有什么数学运算可以加快这个过程?

【问题讨论】:

    标签: c++ algorithm opencv search


    【解决方案1】:

    对于二值图像,可以直接使用HU-Moments和Mahalanobis距离来判断图像A与图像B是否相似。如果距离趋于0,则图像相同。

    当然,您也可以使用特征检测器,因此请查看什么匹配,但对于此类图片,HU Moments 或特征检测器将给出大致相同的结果,但 HU Moments 更有效。

    使用 findContours,您可以提取白星内部的黑色区域并填充它们,以使图像 A = 图像 B。

    其他方法:在您的蒙版上使用 findContours 并将结果应用于图像 A(提取感兴趣区域),您可以提取星星内部的内容并计算您有多少黑色像素(不匹配的像素)。

    【讨论】:

    • 对不起!我修改了我的问题以使其清楚。我不是在比较这些图像中的特征!我想用蒙版计算图像中匹配像素的总数!
    【解决方案2】:

    我有同样的要求,我尝试了几乎相同的方法。如图所示,我想匹配城堡。城堡有不同的盾牌图像和可变长度的氏族名称以及草背景(此图像来自游戏 Clash of Clans)。正常的 opencv matchTemplate 不起作用。所以我自己写。 我按照 matchTemplate 的方式创建结果图像,但使用不同的算法。 核心思想是统计掩码下匹配的像素。代码如下,很简单。 这工作正常,但时间成本很高。如您所见,它花费了 457 毫秒。 现在我正在优化。

    源图像和模板图像都是CV_8U3C,掩码图像是CV_8U。匹配一个通道就可以了。它速度更快,但成本仍然很高。

    Mat tmp(matTempl.cols, matTempl.rows, matTempl.type());
    
    int matchCount      = 0;
    float maxVal        = 0;
    double areaInvert   = 1.0 / countNonZero(matMask);
    
    for (int j = 0; j < resultRows; j++)
    {
        float* data = imgResult.ptr<float>(j);
        for (int i = 0; i < resultCols; i++)
        {
            Mat matROI(matSource, Rect(i, j, matTempl.cols, matTempl.rows));
    
            tmp.setTo(Scalar(0));
            bitwise_xor(matROI, matTempl, tmp);
            bitwise_and(tmp, matMask, tmp);
    
            data[i] = 1.0f - float(countNonZero(tmp) * areaInvert);
            if (data[i] > matchingDegree)
            {
                SRect rc;
                rc.left     = i;
                rc.top      = j;
                rc.right    = i + imgTemplate.cols;
                rc.bottom   = j + imgTemplate.rows;
                rcOuts.push_back(rc);
    
                if ( data[i] > maxVal)
                { 
                    maxVal = data[i]; 
                    maxIndex = rcOuts.size() - 1;
                }
    
                if (++matchCount == maxMatchs)
                {
                    Log_Warn("Too many matches, stopped at: " << matchCount);
                    return true;
                }
            }
        }
    }
    

    它说我没有足够的声誉来发布图片.... http://i.stack.imgur.com/mJrqU.png

    新增: 我通过使用关键点成功地优化了算法。计算所有点是成本,但只计算服务器关键点更快。看图,成本大大降低,现在是7ms左右。

    我还是不能发图,请访问:http://i.stack.imgur.com/ePcD9.png

    请给我声望,以便我发布图片。 :)

    【讨论】:

      【解决方案3】:

      OpenCV Documentation中有一个模板匹配mask的技术公式,效果很好。它可以通过调用cv::matchTemplate 来使用,它的源代码也是Intel License 下的available

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-09
        • 1970-01-01
        • 1970-01-01
        • 2018-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多