OPENCV C - 查找图像中包含的图像

OpenCV C++ - Find an image contained within an image?

本文关键字:图像 包含 查找 OPENCV      更新时间:2023-10-16

我有搜索一个小图像的代码:

int* MyLib::MatchingMethod(int, void*)
{
    /// Source image to display
    img.copyTo(img_display);
    /// Create the result matrix
    int result_cols = img.cols - templ.cols + 1;
    int result_rows = img.rows - templ.rows + 1;
    result.create(result_rows, result_cols, CV_32FC1);
    match_method = 0;
    /// Do the Matching and Normalize
    matchTemplate(img, templ, result, match_method);
    normalize(result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
    /// Localizing the best match with minMaxLoc
    double minVal;
    double maxVal;
    cv::Point minLoc;
    cv::Point maxLoc;
    cv::Point matchLoc;
    minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
    /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
    if (match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED)
    {
        matchLoc = minLoc;
    }
    else
    {
        matchLoc = maxLoc;
    }
    if (showOpenCVWindow) {
        /// Show me what you got
        rectangle(img_display, matchLoc, cv::Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), cv::Scalar(255, 0, 0, 255), 2, 8, 0);
        rectangle(result, matchLoc, cv::Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), cv::Scalar(255, 0, 0, 255), 2, 8, 0);
        imshow(image_window, img_display);
        imshow(result_window, result);
    }
    double  myX = (matchLoc.x + (templ.cols) / 2);
    double  myY = (matchLoc.y + (templ.rows) / 2);
    static int o[2];
    o[0] = myX;
    o[1] = myY;
    return o;
}

但是,即使较大的图像不包含小图像,此代码也可能会错误地"找到"任何区域。

如何更改此代码,将其迫使其"准确"搜索小图像。例如,如果较小的图像不在较大的图像上,则此代码必须显示任何信息消息"未找到图像"。

更新1。看起来像matchTemplate无法正常工作。例如,我有3个图像 - 一个模板(http://s6.postimg.org/nj2ts3lf5/image.png),一个图像,其中包含来自Template(http://s6.postimg.org.org.org.org.org.org.org/fpp6tkggg301/imimage from Template)。

对于第一个图像,包含模板,maxval = 0.9999999403955522及其正确选择的区域:http://s6.postimg.org/65x4qzfht/image.png

但对于图像,不包含模板,MaxVal = 1.00000000000000000000 和IT 错误地选定区域,t包含模板图像:http://s6.postimg.org/5132llt0x/screenshot_544.png

谢谢!

您正在可视化结果,无论算法执行匹配的确定性。模板匹配将始终为您提供输出 - 您想做的就是尝试找出是否有效。

根据match_method尝试输出minValmaxVal。在找到正确匹配的情况下以及在给您误报的情况下,您应该比较值。这些实验应允许您建立一个阈值,从而区分真正的命中和误报。因此,您将能够说出大小 - 例如,Maxval必须确保它是匹配的。伪代码会像这样:

if maxVal > threshold:
     match_found = true
     match_position = maxLoc

现在这是一种理论方法。由于您没有提供任何图像,因此可能不是解决问题的解决方案。

编辑:如果您找不到确定的阈值值(我认为在大多数情况下,如果您保持质量,尺寸等),请尝试做两件事之一:

  1. 尝试查看minMaxLoc之前的所有获得的结果,计算平均值,并查看发现的maxVal是否比真实阳性情况中的平均值大得多。也许您可以将阈值定义为平均值的%,因此说:if maxVal > meanVal + meanVal * n%: match_found = true
  2. 这是一个常见的情况,模板匹配的边缘比真实图像更好。同样,您尚未提供样品,因此很难说在这里将有多可靠。但是,如果您有足够的高频率,以点亮具有巧妙边缘的图像,这可能会使您有更明显的阈值来区分真实和误报。

edit2:由于您使用的是match_method = 0,这意味着 CV_TM_SQDIFF。有关对过程的更多控制,请明确使用名称。在此处查找有关方法的信息。

另外,将cout放入if语句中,以便打印正确的值,实际上是匹配匹配的(在您的情况下,是Minval)。

if (match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED)
{
    matchLoc = minLoc;
    std::cout << minVal << std::endl;
}
else
{
    matchLoc = maxLoc;
    std::cout << maxVal << std::endl;
}

又一次:如果这不给您预期的结果,几乎可以肯定会有所帮助。