简体   繁体   中英

openCV - Using matchTemplate() from a window using hWND 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM