openCV - Using matchTemplate() from a window using hWND C++ - c++

I am running an infinite loop and every frame I'm taking a screenshot from a desired window and turning it into a Mat then searching that Mat for a template image using matchTemplate. If I read in the template image and the entire image, I can use the function successfully using the TM_SQDIFF method. However, when I run the below code, a rectangle is always drawn even if the template isn't there and is never over the template if the template is present. Any ideas?
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include "opencv2/imgproc.hpp"
#include <Windows.h>
#include <iostream>
using namespace std;
using namespace cv;
Mat getMat(HWND hWND);
int main()
{
//Window capture
LPCWSTR windowTitle = L"imgName - Paint";
HWND hWND = FindWindow(NULL, windowTitle);
while (!hWND)
{
system("cls");
cout << "Start game" << endl;
hWND = FindWindow(NULL, windowTitle);
Sleep(100);
}
enum TemplateMatchModes
{
TM_SQDIFF = 0,
TM_SQDIFF_NORMED = 1,
TM_CCORR = 2,
TM_CCORR_NORMED = 3,
TM_CCOEFF = 4,
TM_CCOEFF_NORMED = 5
};
TemplateMatchModes option = TM_SQDIFF;
Mat templateImage = imread("images/templateImg.jpg", IMREAD_COLOR);
Mat otherThing;
templateImage.convertTo(otherThing, CV_8UC4);
namedWindow("Result", WINDOW_NORMAL);
while (true)
{
double minVal;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
Mat theImage = getMat(hWND);
Mat result;
Mat background;
theImage.copyTo(background);
cvtColor(theImage, theImage, COLOR_BGR2HSV);
matchTemplate(theImage, otherThing, result, option);
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (option == TM_SQDIFF || option == TM_SQDIFF_NORMED)
{
matchLoc = minLoc;
}
else
{
matchLoc = maxLoc;
}
rectangle(background, matchLoc, Point(matchLoc.x + otherThing.cols, matchLoc.y + otherThing.rows), Scalar(0, 255, 0), 2, 8, 0);
imshow("Result", background);
waitKey(30);
}
}
Mat getMat(HWND hWND)
{
HDC deviceContext = GetDC(hWND);
HDC memoryDeviceContext = CreateCompatibleDC(deviceContext);
RECT windowRect;
GetClientRect(hWND, &windowRect);
int height = windowRect.bottom;
int width = windowRect.right;
HBITMAP bitmap = CreateCompatibleBitmap(deviceContext, width, height);
SelectObject(memoryDeviceContext, bitmap);
BitBlt(memoryDeviceContext, 0, 0, width, height, deviceContext, 0, 0, SRCCOPY);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = -height;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 1;
bi.biYPelsPerMeter = 1;
bi.biClrUsed = 1;
bi.biClrImportant = 1;
Mat mat = Mat(height, width, CV_8UC4);
GetDIBits(memoryDeviceContext, bitmap, 0, height, mat.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
DeleteObject(bitmap);
DeleteDC(memoryDeviceContext);
ReleaseDC(hWND, deviceContext);
return mat;
}

There is no condition given for rectangle to not to be drawn. If you want it to be drawn only if the template found you should create a condition for that.
You may check some detection examples as well.

Related

opencv + cuda how to record video from the screen at 64 fps?

Good afternoon.
At the moment I cannot find information on how to record video from the screen using opencv + cuda at 64 fps. I have some code that uses cpu but not gpu, so it's about 25 fps. Please help me find information.
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/cudaarithm.hpp>
#include <opencv2/video.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <Windows.h>
using namespace std;
using namespace cv;
using namespace cv::cuda;
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 / 1; //change this to whatever size you want to resize to
width = windowsize.right / 1;
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;
}
int main(int argc, char** argv)
{
HWND hwndDesktop = GetDesktopWindow();
//namedWindow("output", WINDOW_NORMAL);
int key = 0;
while (1)
{
Mat src = hwnd2mat(hwndDesktop);
// you can do some image processing here
imshow("output", src);
key = waitKey(1);
}
}
how to record video from desktop at 64 fps?
I tried to replace MAT with UMAT, which uses mostly gpu, but unfortunately it didn't work because of this function:
GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
Because the UMAT class has no variable data.
Edit:
Good afternoon, I updated the hwnd2mat function for gpu, but it gives me a black screen for some reason. Help me please.
UMat hwnd2mat(HWND hwnd)
{
HDC hwindowDC, hwindowCompatibleDC;
int height, width, srcheight, srcwidth;
HBITMAP hbwindow;
UMat 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 / 1; //change this to whatever size you want to resize to
width = windowsize.right / 1;
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.u->data, (BITMAPINFO*)&bi, DIB_RGB_COLORS); //copy from hwindowCompatibleDC to hbwindow
// avoid memory leak
DeleteObject(hbwindow);
DeleteDC(hwindowCompatibleDC);
ReleaseDC(hwnd, hwindowDC);
return src;
}
CUDA helps to accelerate processing functions, but cannot help in accelerating capture of desktop. In this case, bottleneck is the blit API you are using to capture the screen (GetDIBits). Since you seem to be having a Nvidia GPU, you should look at OS/driver level alternatives like mentioned here (https://developer.nvidia.com/capture-sdk).

OpenCV Read Mat from Memory returns null

I create a MAT from a given hWnd
cv::Mat hwnd2mat(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;
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;
}
And I try to load the images to run the template matching algorithm.
However, when I try to imgdecode I get img = NULL. If I save the file to a png and read it afterwards, it's working.
I even tried to use the different flags to read the image.
cv::Mat resMat = hwnd2mat(blueStackshWnd);
cv::imwrite("foo.png", resMat);
img = cv::imdecode(resMat, cv::IMREAD_GRAYSCALE);
//img = cv::imread("fuck.png", cv::IMREAD_COLOR);
templ = cv::imread("images\\giant.png", cv::IMREAD_GRAYSCALE);
Here is a screenshot while debugging
EDIT:
When assigning the ret value of hwnd2mat to img I get the following error
error: (-215) (depth == 0 || depth == 5) && type == _templ.type() && _img.dims() <= 2 in function cv... ...} ...} const cv::Exception &

c++ opencv displaying image on a window

I want to load an image using OpenCV and then display it on a window.
I know how to load an image using opencv and how to create a window using win32 but how do I go about putting the image / mat from Opencv on the window afterwards?
This is how I load the image from opencv:
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
string imageName("C:/image.jpg"); // by default
if (argc > 1)
{
imageName = argv[1];
}
Mat image;
image = imread(imageName.c_str(), IMREAD_COLOR);
if (image.empty())
{
cout << "Could not open or find the image" << std::endl;
return -1;
}
namedWindow("Display window", WINDOW_AUTOSIZE);
imshow("Display window", image);
waitKey(0);
return 0;
}
EDIT: The reason I want to do this is actually not to create a window during runtime and then display the image on it, but rather I want to find a window using win32's FindWindow function and then draw an image on that :D
I'm using this pretty often with my MFC projects. If you only have hwnd, not CWnd, then you may have to change a bit.
This works both with 8-bit RGB color and 1-channel monochrome image.
void DrawImage( CWnd *wnd, int width, int height, int bpp, const unsigned char *buffer)
{
RECT rect;
wnd->GetWindowRect(&rect);
CDC *dc = wnd->GetDC();
if( bpp == 3) // BGR
{
BITMAPINFO bmpinfo;
memset(&bmpinfo, 0, sizeof(bmpinfo));
bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biBitCount = 24;
bmpinfo.bmiHeader.biClrImportant = 0;
bmpinfo.bmiHeader.biClrUsed = 0;
bmpinfo.bmiHeader.biCompression = BI_RGB;
bmpinfo.bmiHeader.biWidth = width;
bmpinfo.bmiHeader.biHeight = -height;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biSizeImage = 0;
bmpinfo.bmiHeader.biXPelsPerMeter = 100;
bmpinfo.bmiHeader.biYPelsPerMeter = 100;
::SetStretchBltMode( dc->GetSafeHdc(), COLORONCOLOR);
::StretchDIBits( dc->GetSafeHdc(),
0,
0,
rect.right - rect.left,
rect.bottom - rect.top,
0,
0,
width,
height,
buffer,
&bmpinfo,
DIB_RGB_COLORS,
SRCCOPY);
}
else if ( bpp == 1) // monochrome.
{
char bitmapInfoBuf[sizeof(BITMAPINFO) + 4 * 256];
BITMAPINFO* pBmpInfo = (BITMAPINFO*)bitmapInfoBuf;
memset(pBmpInfo, 0, sizeof(BITMAPINFO) + 4 * 256);
pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biWidth = width;
pBmpInfo->bmiHeader.biHeight = -height;
pBmpInfo->bmiHeader.biCompression = BI_RGB;
pBmpInfo->bmiHeader.biPlanes = 1;
pBmpInfo->bmiHeader.biBitCount = 8;
for(int i = 0; i < 256; i++)
{
pBmpInfo->bmiColors[i].rgbBlue=i;
pBmpInfo->bmiColors[i].rgbGreen=i;
pBmpInfo->bmiColors[i].rgbRed=i;
pBmpInfo->bmiColors[i].rgbReserved=255;
}
::SetStretchBltMode( dc->GetSafeHdc(), COLORONCOLOR);
::StretchDIBits( dc->GetSafeHdc(),
0,
0,
rect.right - rect.left,
rect.bottom - rect.top,
0,
0,
width,
height,
buffer,
pBmpInfo,
DIB_RGB_COLORS,
SRCCOPY);
}
wnd->ReleaseDC(dc);
}
void DrawCVImage(cv::Mat image, CWnd *picture)
{
if (image.cols % 4 == 0)
{
DrawImage(picture,
image.cols,
image.rows,
image.channels() == 3 ? 3 : 1,
image.data);
}
else
{
Mat image2(image.rows, image.cols + ( 4 - image.cols % 4), image.type());
image2 = 0;
image.copyTo(image2(Rect(0, 0, image.cols, image.rows)));
DrawImage(picture,
image2.cols,
image2.rows,
image2.channels() == 3 ? 3 : 1,
image2.data);
}
}
Well...
Don't create a new window by calling "namedWindow()".
Then call imshow(nameOfExistingWindow, image).
Maybe it will work.

OPENCV desktop capture Part II

Continuing in previous post from here OPENCV Destop Capture and this hwnd2mat function, a method to capture desktop as source in opencv is create a bitmap from the screen image with this hwnd2mat function. done.
this function is already create a bitmap from the screen image.but it gives weird effect like a trailing inside the video, i just want a normal video source more likely like this one . i've already try to find what cause it, but i don't know anymore.
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <Windows.h>
#include <iostream>
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 / 1; //change this to whatever size you want to resize to
width = windowsize.right / 1;
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;
}
int main(int argc, char **argv)
{
HWND hwndDesktop = GetDesktopWindow();
namedWindow("output", CV_WINDOW_NORMAL);
int key = 0;
while (key != 30 )
{
Mat src = hwnd2mat(hwndDesktop);
// you can do some image processing here
imshow("output", src);
key = waitKey(30); // you can change wait time
}
ReleaseCapture();
destroyAllWindows();
return 0;
}
Using GetDesktopWindow() will make infinite-mirror-effect, instead that, using what window you want capture, and me, i'm using FindWindowEx(), and use Spy++ to find what window you want to capture, that should works. but of course it will go to the next bug :).

OpenCV: assertation failed ((img.depth() == CV_8U || img.depth() == CV_32F) && img.type() == templ.type())

I get this error from above and don't know how to avoid it.
My aim is to get a screenshot and then perform a template matching on it to see if an icon is shown on the screen at this moment. Till now it's just the position of the icon.
My code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
using namespace cv;
Mat hwnd2mat();
/// Global Variables
Mat img; Mat templ; Mat result;
int main()
{
/// Load image and template
templ = imread( "Template.bmp",1);
templ.convertTo(templ, CV_8U);
//img = imread( "Image.jpg", 1 );
img = hwnd2mat();
/// Create the result matrix
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_8U);
/// Do the Matching and Normalize
matchTemplate( img, templ, result, CV_TM_SQDIFF );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
/// show best position
matchLoc = minLoc;
cout<<matchLoc<<" is best position"<<endl;
waitKey(0);
return 0;
}
Mat hwnd2mat(){
HWND hwnd = GetDesktopWindow();
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/1; //change this to whatever size you want to resize to
width = windowsize.right/1;
src.create(height,width,CV_8U);
// 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
DeleteObject(hbwindow);
DeleteDC(hwindowCompatibleDC);
ReleaseDC(hwnd, hwindowDC);
return src;
}
The function with the screenshot is not my own work, i got it from here
Any Ideas what to do?
Thanks for help, best regards!
The problem is that the function hwnd2mat is returning a grayscale image of type CV_8UC1 while templ is a color image of type CV_8UC3. So the assertion is failing on the function matchTemplate due to the failing condition img.type() == templ.type(). You may load the image as grayscale to avoid the error.
templ = imread( "Template.bmp",CV_LOAD_IMAGE_GRAYSCALE);
UPDATE:
It is worth noting that the function hwnd2mat is not working in its current form and it returns an invalid image. The original code creates the output image of type CV_8UC4 which is the correct approach.
src.create(height,width,CV_8UC4);
Either you may convert src to grayscale before returning from hwnd2mat, or you may convert templ to 4 channel image. Anyway, the point is that both image must have same type for matchTemplate to work.