OpenCV C ++-查找图像中包含的图像? [英] OpenCV C++ - Find an image contained within an image?

查看:105
本文介绍了OpenCV C ++-查找图像中包含的图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有用于在大另一幅图像中搜索一个小图像的代码:

I have code for searching one small image in bigger another one image:

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

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

But this code could mistakenly "found" any area, even if bigger image doesn't contains small image.

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

How to change this code, to force it to "exactly" searching of the small image. For example, if smaller image is not on the bigger image, this code must show any info message "Image not found".

更新1.看起来像matchTemplate不能正常工作.例如,我有3张图片-一个模板( http://s6.postimg.org/nj2ts3lf5 /image.png ),其中一幅图像包含模板中的图像( http://s6.postimg.org/fp6tkg301/image.png )和一个不包含模板的图像( http://s6.postimg.org/9x23zk3sh/image.png ).

Update 1. It looks, like matchTemplate doesn't work good. For example, I have 3 images - one template ( http://s6.postimg.org/nj2ts3lf5/image.png ) , one image, that contains image from template ( http://s6.postimg.org/fp6tkg301/image.png ), and one image, that doesn't contains template ( http://s6.postimg.org/9x23zk3sh/image.png ).

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

For first image, that contains template, maxVal=0.99999994039535522 and it correctly selected area: http://s6.postimg.org/65x4qzfht/image.png

但是对于图像,包含模板maxVal = 1.0000000000000000 ,并且它错误地选择了区域, t包含模板图片: http://s6.postimg.org/5132llt0x/screenshot_544 .png

But for image, that doesn't contains template, maxVal=1.0000000000000000 and it incorrectly selected area, that doesn't contains template image: http://s6.postimg.org/5132llt0x/screenshot_544.png

谢谢!

推荐答案

您正在可视化结果,而不管算法执行匹配的确定性如何.模板匹配将始终为您提供输出-您要做的是尝试找出它是否有效.

You are visualizing the result regardless of the certainty with which the algorithm performed matching. Template matching will always give you an output - what you want to do is to try to figure out if it's valid or not.

尝试根据match_method输出minValmaxVal.在找到正确匹配的情况下和给您误报的情况下,您应该比较该值.这些实验应允许您建立一个阈值,以区分真假和假阳性.因此,您将能够说出maxVal的大小,例如,必须确保maxVal是匹配的.伪代码将如下所示:

Try outputing minVal or maxVal depending on the match_method. You should compare the value in the cases when the correct match was found and in the cases when it gave you a false positive. Those experiments should allow you to establish a threshold, that distinguishes between true hits and false positives. Thus, you will be able to say how big - for example - the maxVal has to be to be sure that it was a match. Pseudo code would go something like this:

if maxVal > threshold:
     match_found = true
     match_position = maxLoc

现在,这是一种理论方法.由于您未提供任何图像,因此它可能会也可能不会解决您的问题.

Now that's a theoretical approach. Since you didn't provide any images, it might or might not be the solution for your problem.

如果您找不到确定的阈值(我认为,在大多数情况下,如果您保持质量,尺寸等,应该可以这样做),请尝试执行以下两种操作之一:

If you cannot find a definite threshold value (which in my opinion should be possible in most cases, if you maintain quality, size, etc), try doing one of two things:

  1. minMaxLoc之前尝试查看所有获得的结果,计算平均值,然后查看找到的maxVal是否比真实阳性病例的平均值大得多.也许您可以将阈值定义为平均值的百分比,这样说:if maxVal > meanVal + meanVal * n%: match_found = true
  2. 常见的情况是,模板匹配在边缘上比在真实图像上效果更好.同样,您没有提供示例,因此很难说这种方法的可靠性.但是,如果您有足够高的频率,可以使用Canny Edges照亮图像,则可能会为您区分真假阳性提供一个更清晰的阈值.
  1. Try looking at all obtained results, before minMaxLoc, calculate the mean value and see if the maxVal found is much bigger than the mean value in the true positive cases. Maybe you can define the threshold as the % of the mean value, thus saying: if maxVal > meanVal + meanVal * n%: match_found = true
  2. It is a common situation, that template matching works better with edges than with the real image. Again, you haven't provided samples, so it's hard to say how reliable will that approach be here. But if you have enough high frequencies, to light up an image with Canny Edges, that might give you a much clearer threshold for discriminating between true and false positives.

由于您使用的match_method = 0,这意味着CV_TM_SQDIFF.要对过程进行更多控制,请显式使用名称.在此处中找到有关方法的信息.

Since you're using match_method = 0, that means CV_TM_SQDIFF. For more control over the process, use the name explicitly. Find information on the methods here.

另外,将cout放在if语句内,以便您打印正确的值,该值实际上是对匹配的识别(在您的情况下为minVal).

Also, put the cout inside the if statement, so that you print the correct value, that actually idicates the match (in your case, it's 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;
}

再说一遍:合理调整的轮廓检测几乎可以肯定会在没有给您预期结果的情况下有所帮助.

And again: fairly tuned contours detection should almost certainly help if this doesn't give you the expected results.

这篇关于OpenCV C ++-查找图像中包含的图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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