0

我正在运行一个无限循环,每一帧我都从所需的窗口截取屏幕截图并将其转换为 Mat,然后使用 matchTemplate 在该 Mat 中搜索模板图像。如果我读入模板图像和整个图像,我可以使用 TM_SQDIFF 方法成功使用该函数。但是,当我运行下面的代码时,即使模板不存在,也会始终绘制一个矩形,并且如果模板存在,则永远不会超过模板。有任何想法吗?

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

1 回答 1

1

没有给出不绘制矩形的条件。如果您希望仅在找到模板时才绘制它,您应该为此创建一个条件。

您也可以查看一些检测示例

于 2021-11-11T13:39:26.610 回答