问题描述
我有一个小模板图像,用于在较大的屏幕截图中查找匹配子图像的坐标。屏幕截图本身在 BitBlt
的帮助下捕获到内存DC中,然后通过转换为 cv :: Mat
GetDIBits
,如下所示:
I have a small template image which is meant to be used to find coordinates of matching subimages within a larger screenshot image. The screenshot itself is captured into a memory DC with the help of BitBlt
, then converted into a cv::Mat
via GetDIBits
, like so:
HDC windowDc = GetWindowDC(hwndTarget);
HDC memDc = CreateCompatibleDC(windowDc);
// ...
HBITMAP hbmp = CreateCompatibleBitmap(windowDc, width, height);
SelectObject(memDc, hbmp);
BITMAPINFOHEADER bi =
{
sizeof(BITMAPINFOHEADER), // biSize
width, // biWidth
-height, // biHeight
1, // biPlanes
32, // biBitCount
BI_RGB, // biCompression
0, // biSizeImage
0, // biXPelsPerMeter
0, // biYPelsPerMeter
0, // biClrUser
0 // biClrImportant
};
// ...
BitBlt(memDc, 0, 0, width, height, windowDc, offsetX, offsetY, SRCCOPY);
matScreen.create(height, width, CV_8UC4);
GetDIBits(memDc, hbmp, 0, (UINT)height, matScreen.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
这看起来工作正常,并且快速 imshow
This appears to work fine, and a quick imshow("Source", matScreen)
displays the image correctly.
屏幕截图图像已创建为32位RGB内存位图,并放置在 cv :: Mat
中使用 CV_8UC4
标志,它在OpenCV中失败几个断言(以及当使用几个OpenCV方法时输出麻烦的结果)。最值得注意的是, matchTemplate
总是在以下行中失败:
Since this screenshot image has been created as a 32-bit RGB memory bitmap, and placed inside a cv::Mat
using the CV_8UC4
flag, it fails several assertions in OpenCV (as well as outputs whacky results when utilizing several OpenCV methods). Most notably, matchTemplate
always fails on the following line:
CV_Assert( (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 );
我试过匹配截图的深度标记和模板/结果Mats,最好的情况是我能够显示所有3张图片,但模板匹配不工作,因为我假设源(屏幕截图)图像显示为彩色,而其他的是灰度。其他转换失败,或显示奇怪的结果和失败的模板匹配(或只是提出一个错误)...和更改截图图像的 Mat
使用任何其他深度标志结束
I've tried matching up the depth flags of the screenshot and the template/result Mats, and the best case scenario is that I am able to display all 3 images, but the template matching doesn't work because I'm assuming the source (screenshot) image is displayed in color whilst the others are in grayscale. Other conversions either fail, or display strange results and fail the template matching (or simply raise an error)... And changing the screenshot image's Mat
to use any other depth flag ends up displaying the image incorrectly.
我可以使用OpenCV的模板匹配和截图在C ++?是否有某种手动转换我应该对截图图像,或者什么?
What can I do to utilize OpenCV's template matching with a screenshot taken in C++? Is there some sort of manual conversion I should be doing to the screenshot image, or something?
截图代码摘自:
我的主要代码:
推荐答案
我已经包括我的代码从您的桌面图像中查找模板图像。希望这解决了您的问题!
Hi i have included my code for finding a Template image from your Desktop image. Hope this solves your problem!
#include <fstream>
#include <memory>
#include <string>
#include <iostream>
#include <strstream>
#include <functional>
#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;
using namespace cv;
Mat hwnd2mat(HWND hwnd){
HDC hwindowDC,hwindowCompatibleDC;
int height,width,srcheight,srcwidth;
HBITMAP hbwindow;
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; //change this to whatever size you want to resize to
width = windowsize.right;
src.create(height,width,CV_8UC4);
// create a bitmap
hbwindow = CreateCompatibleBitmap( hwindowDC, width, height);
bi.biSize = sizeof(BITMAPINFOHEADER); //http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
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;
}
bool NMultipleTemplateMatching(Mat mInput,Mat mTemplate,float Threshold,float Closeness,vector<Point2f> &List_Matches)
{
Mat mResult;
Size szTemplate= mTemplate.size();
Size szTemplateCloseRadius((szTemplate.width/2)* Closeness,(szTemplate.height/2)* Closeness);
matchTemplate(mInput, mTemplate, mResult, TM_CCOEFF_NORMED);
threshold(mResult, mResult, Threshold, 1.0, THRESH_TOZERO);
while (true)
{
double minval, maxval ;
Point minloc, maxloc;
minMaxLoc(mResult, &minval, &maxval, &minloc, &maxloc);
if (maxval >= Threshold)
{
List_Matches.push_back(maxloc);
rectangle(mResult,Point2f(maxloc.x-szTemplateCloseRadius.width,maxloc.y-szTemplateCloseRadius.height),Point2f(maxloc.x+szTemplateCloseRadius.width,maxloc.y+szTemplateCloseRadius.height),Scalar(0),-1);
}
else
break;
}
//imshow("reference", mDebug_Bgr);
return true;
}
int main(int argc, char** argv)
{
Mat mTemplate_Bgr,mTemplate_Gray;
mTemplate_Bgr= imread("Template.png",1);
imshow("mTemplate_Bgr",mTemplate_Bgr);
HWND hDesktopWnd;
hDesktopWnd=GetDesktopWindow();
Mat mScreenShot= hwnd2mat(hDesktopWnd);
Mat mSource_Gray,mResult_Bgr= mScreenShot.clone();
float Threshold= 0.9;
float Closeness= 0.9;
vector<Point2f> List_Matches;
cvtColor(mScreenShot,mSource_Gray,COLOR_BGR2GRAY);
cvtColor(mTemplate_Bgr,mTemplate_Gray,COLOR_BGR2GRAY);
namedWindow("Screen Shot",WINDOW_AUTOSIZE);
imshow("Screen Shot",mSource_Gray);
NMultipleTemplateMatching(mSource_Gray,mTemplate_Gray,Threshold,Closeness,List_Matches);
for (int i = 0; i < List_Matches.size(); i++)
{
rectangle(mResult_Bgr,List_Matches[i],Point(List_Matches[i].x + mTemplate_Bgr.cols, List_Matches[i].y + mTemplate_Bgr.rows),Scalar(0,255,0), 2);
}
imshow("Final Results",mResult_Bgr);
waitKey(0);
return 0;
}
请接受此回答&如果这有助于你,请投票!
Please accept this answer & Vote up if this helps you!
这篇关于从窗口的屏幕截图的模板匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!