Opencv 在图像中查找图标

Opencv 在图像中查找图标,opencv,computer-vision,emgucv,aforge,Opencv,Computer Vision,Emgucv,Aforge,我刚刚开始学习计算机视觉,正在做一个简单的项目,在静止图像中找到基本的图标 我有一个模板图像: 和两个测试图像: 及 我使用了模板匹配(使用forge.net,但我认为是相同的算法) OpenCV和Emgu使用。我可能错了,我是CV新手)并发现阈值为.80563时,我会在上述两种图像中找到完全匹配的一个,但在我尝试的图像中没有找到匹配的图标 我以为我已经有进展了,直到我看到了每个图像中作为匹配返回的内容:(蓝色突出显示的方块是图像匹配的地方。) (正确)和(完全错误) 我意识到问题在于以下任

我刚刚开始学习计算机视觉,正在做一个简单的项目,在静止图像中找到基本的图标

我有一个模板图像:

和两个测试图像:

我使用了模板匹配(使用forge.net,但我认为是相同的算法) OpenCV和Emgu使用。我可能错了,我是CV新手)并发现阈值为.80563时,我会在上述两种图像中找到完全匹配的一个,但在我尝试的图像中没有找到匹配的图标

我以为我已经有进展了,直到我看到了每个图像中作为匹配返回的内容:(蓝色突出显示的方块是图像匹配的地方。)

(正确)和(完全错误)

我意识到问题在于以下任何或所有方面:

  • 我正在寻找的图标在大小、颜色和阴影方面都很相似,但不能保证它们在上述任何一个方面都是相同的。(注意:角度方向和比例应该一致。我不希望一个带“+”的圆与模板匹配。我也不希望一个带小“X”的大圆匹配。)
  • 我的模板不是正方形,我只是猜测透明像素不会包含在匹配中
  • 鉴于上述两个问题,模板匹配可能是错误的方法。也许我需要用别的东西来做这个

最后,我需要一些基本的帮助来了解我的匹配出了什么问题,这样我至少可以回到正确的方向。模板是否匹配正确的方法,但我需要更改一些内容?或者我需要看看这些库中的其他功能吗?对于这个简单的任务,OpenCV(和EMGU)功能和arge.net功能之间有很大的功能区别吗?

在这种情况下,模板匹配是正确的选择,但您必须正确执行:

  • 您的模板与您要查找的内容不符。在第二张图像中,由于按钮的灰度值与背景中的某个位置更为相似,因此结果不好。如果要搜索白色十字,请使用白色十字作为填塞板,如下所示:

  • 不要使用固定阈值,而是搜索最高响应点
根据这些指南,您可以找到您的按钮(红色小矩形):

以下是OpenCV(C++)中的代码示例:

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    // Load template and image
    Mat3b templ = imread("path_to_template");
    Mat3b img = imread("path_to_image");

    // Convert to grayscale
    Mat1b img_gray;
    Mat1b templ_gray;
    cvtColor(img, img_gray, COLOR_BGR2GRAY);
    cvtColor(templ, templ_gray, COLOR_BGR2GRAY);

    // Match template
    Mat1f result;
    matchTemplate(img, templ, result, TM_CCOEFF_NORMED);

    // Find highest response
    Point maxLoc;
    minMaxLoc(result, NULL, NULL, NULL, &maxLoc);

    // Draw the red rectangle
    rectangle(img, Rect(maxLoc, templ.size()), Scalar(0,0,255), 2);

    // Show results
    imshow("Result", img);
    waitKey();

    return 0;
}
#包括
使用名称空间cv;
int main()
{
//加载模板和图像
Mat3b templ=imread(“路径到模板”);
Mat3b img=imread(“路径到图像”);
//转换为灰度
Mat1b img_gray;
Mat1b templ_gray;
CVT颜色(img、img_灰色、颜色_BGR2灰色);
CVT颜色(模板、模板灰、颜色灰);
//匹配模板
Mat1f结果;
匹配模板(img、temp、result、TM\u cceff\u NORMED);
//找到最高响应
maxLoc点;
minMaxLoc(结果、NULL、NULL、NULL和maxLoc);
//画一个红色的矩形
矩形(img,Rect(maxLoc,temp.size()),标量(0,0255),2);
//显示结果
imshow(“结果”,img);
waitKey();
返回0;
}

在这种情况下,模板匹配是正确的选择,但您必须正确执行:

  • 您的模板与您要查找的内容不符。在第二张图像中,由于按钮的灰度值与背景中的某个位置更为相似,因此结果不好。如果要搜索白色十字,请使用白色十字作为填塞板,如下所示:

  • 不要使用固定阈值,而是搜索最高响应点
根据这些指南,您可以找到您的按钮(红色小矩形):

以下是OpenCV(C++)中的代码示例:

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    // Load template and image
    Mat3b templ = imread("path_to_template");
    Mat3b img = imread("path_to_image");

    // Convert to grayscale
    Mat1b img_gray;
    Mat1b templ_gray;
    cvtColor(img, img_gray, COLOR_BGR2GRAY);
    cvtColor(templ, templ_gray, COLOR_BGR2GRAY);

    // Match template
    Mat1f result;
    matchTemplate(img, templ, result, TM_CCOEFF_NORMED);

    // Find highest response
    Point maxLoc;
    minMaxLoc(result, NULL, NULL, NULL, &maxLoc);

    // Draw the red rectangle
    rectangle(img, Rect(maxLoc, templ.size()), Scalar(0,0,255), 2);

    // Show results
    imshow("Result", img);
    waitKey();

    return 0;
}
#包括
使用名称空间cv;
int main()
{
//加载模板和图像
Mat3b templ=imread(“路径到模板”);
Mat3b img=imread(“路径到图像”);
//转换为灰度
Mat1b img_gray;
Mat1b templ_gray;
CVT颜色(img、img_灰色、颜色_BGR2灰色);
CVT颜色(模板、模板灰、颜色灰);
//匹配模板
Mat1f结果;
匹配模板(img、temp、result、TM\u cceff\u NORMED);
//找到最高响应
maxLoc点;
minMaxLoc(结果、NULL、NULL、NULL和maxLoc);
//画一个红色的矩形
矩形(img,Rect(maxLoc,temp.size()),标量(0,0255),2);
//显示结果
imshow(“结果”,img);
waitKey();
返回0;
}

如果您只想检测一些变化的模式,那么这可能会有些过分。训练haar级联分类器将使您能够更准确地检测此类模式,并且您不必担心阈值。

如果您只想检测具有少量变化的模式,这可能会有些过分。训练haar cascade分类器将使您能够更准确地检测此类模式,并且您不必担心阈值。

谢谢!工作得很有魅力#Miki所以,在熟睡之后,让我看看我是否在这里提炼出一般概念:对于一个好的模板,我想使用最独特的功能,用最少的(不太明显的)环境?没错。在你的例子中,你不是在寻找一个白色的十字架,而是在里面有一个白色十字架的灰色sh区域。所以你得到了灰色sh区域的最高响应,即使它们里面没有十字架。谢谢!工作得很有魅力#Miki所以,在熟睡之后,让我看看我是否在这里提炼出一般概念:对于一个好的模板,我想使用最独特的功能,用最少的(不太明显的)环境?没错。在你的例子中,你不是在寻找一个白色的十字架,而是在里面有一个白色十字架的灰色sh区域。因此,灰色sh区域的响应最高,即使它们内部没有十字。