0

I'm trying to use OpenCV for template matching of a screenshot. I'm getting an error whenever I call the cv::matchTemplate() function.

The error I'm getting:

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

What I've tried:

This question attempts to solve the problem but the solution doesn't help because that's what I'm already doing. I've double checked everything in the debugger. Nothing is NULL, everything has several rows and columns and 2 dimensions.

Main

HWND handle = GetForegroundWindow();
cv::Mat mat;
if (handle != 0){
    mat = windowToMat(handle);
}
myTemplateMatch(mat, playerTemplate);

Template Matching ---

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

ScreenShot Creation

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;
}
Community
  • 1
  • 1
Daniel
  • 2,435
  • 5
  • 26
  • 40
  • may i see your complete code? i guess there is something missing in this! – Balaji R Jul 25 '15 at 09:01
  • Also have you tried to compile that code separately? – Balaji R Jul 25 '15 at 09:01
  • @BalajiR There wasn't much missing but I added where it was called from. The code complies fine and I can successful call cv::matchTemplate with a non-screenshot template. – Daniel Jul 26 '15 at 05:21

1 Answers1

1

The problem was that the type of Mat images being used was different. If you use the Mat's .type() function you can check the parameters being passed into the function. Cross reference that value with this table

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

and you can change the type of screenshot

src.create(height, width, CV_32F); in Screenshot Creation

to whatever the value should be.

Daniel
  • 2,435
  • 5
  • 26
  • 40