模板匹配屏幕截图在断言上失败

Posted

技术标签:

【中文标题】模板匹配屏幕截图在断言上失败【英文标题】:Template Matching a screenshot fails on assertion 【发布时间】:2015-07-25 02:09:45 【问题描述】:

我正在尝试使用 OpenCV 进行屏幕截图的模板匹配。每当我调用 cv::matchTemplate() 函数时都会出错。

我遇到的错误:

OpenCv Error: Assertion failed ((depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2) in cv::matchTemplate, file C:\builds\master_PackSlave-win64-vc12-shared\opencv\modules\imgproc\src\templmatch.cpp

我的尝试:

This question attempts to solve the problem 但该解决方案无济于事,因为这就是我已经在做的事情。我已经仔细检查了调试器中的所有内容。没有什么是 NULL,一切都有几行多列和 2 个维度。

主要

HWND handle = GetForegroundWindow();
cv::Mat mat;
if (handle != 0)
    mat = windowToMat(handle);

myTemplateMatch(mat, playerTemplate);

模板匹配---

#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/highgui/highgui.hpp>

#include <ctime>

#include <Windows.h>
#include <iostream>
#include <string>
XYposition myTemplateMatch(cv::Mat &img, cv::Mat &mytemplate)

cv::Mat result(img.rows - mytemplate.rows + 1, img.cols - mytemplate.cols + 1, CV_32F);

//***************BREAKS RIGHT HERE****************************
cv::matchTemplate(img, mytemplate, result, CV_TM_SQDIFF_NORMED);
cv::normalize(result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

double minVal; double maxVal; 
cv::Point minLoc; 
cv::Point maxLoc;
cv::Point matchLoc;

cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
XYposition playerData = 
    maxLoc.x + mytemplate.cols, maxLoc.y + mytemplate.rows
;

rectangle(result, matchLoc, cv::Point(matchLoc.x + mytemplate.cols, matchLoc.y + mytemplate.rows),
    cv::Scalar(0, 0, 255), 4, 8, 0);


cv::namedWindow("cvImage", CV_WINDOW_AUTOSIZE);
cv::imshow("cvImage", result);
cv::waitKey(0);

return playerData;

截图创作

cv::Mat windowToMat(HWND hwnd)

HDC hwindowDC, hwindowCompatibleDC;

int height, width, srcheight, srcwidth;
HBITMAP hbwindow;
cv::Mat src;
BITMAPINFOHEADER  bi;

hwindowDC = GetDC(hwnd);
hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);

RECT windowsize;    // get the height and width of the screen
GetClientRect(hwnd, &windowsize);

srcheight = windowsize.bottom;
srcwidth = windowsize.right;
height = windowsize.bottom / 2;  //change this to whatever size you want to resize to
width = windowsize.right / 2;

src.create(height, width, CV_32F);

// create a bitmap
hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = -height;  //this is the line that makes it draw upside down or not
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

// use the previously created device context with the bitmap
SelectObject(hwindowCompatibleDC, hbwindow);
// copy from the window device context to the bitmap device context
StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, 0, 0, srcwidth, srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO *)&bi, DIB_RGB_COLORS);  //copy from hwindowCompatibleDC to hbwindow

// avoid memory leak
DeleteObject(hbwindow); DeleteDC(hwindowCompatibleDC); ReleaseDC(hwnd, hwindowDC);

return src;

【问题讨论】:

我可以看看你的完整代码吗?我想这其中缺少一些东西! 你也试过单独编译那段代码吗? @BalajiR 没有太多遗漏,但我添加了调用它的位置。代码符合要求,我可以使用非屏幕截图模板成功调用 cv::matchTemplate。 【参考方案1】:

问题在于所使用的Mat 图像的类型不同。如果您使用 Mat 的 .type() 函数,您可以检查传递给函数的参数。与此表交叉引用该值

A Mapping of Type to Numbers in OpenCV

        C1  C2  C3  C4
CV_8U   0   8   16  24
CV_8S   1   9   17  25
CV_16U  2   10  18  26
CV_16S  3   11  19  27
CV_32S  4   12  20  28
CV_32F  5   13  21  29
CV_64F  6   14  22  30

你可以改变截图的类型

src.create(height, width, CV_32F);截图创建

到任何值应该是。

【讨论】:

以上是关于模板匹配屏幕截图在断言上失败的主要内容,如果未能解决你的问题,请参考以下文章

java+selenium+new——断言失败时,进行屏幕截图并保存

如何在 Cucumber Report 中自定义软断言期间附加/嵌入捕获的屏幕截图?

如何使用猎犬/ elixir进行屏幕截图

无法在颤动中截取屏幕截图

Selenium 可以截取 JUnit 测试失败的屏幕截图吗?

如何在 testNG 报告中包含失败屏幕截图