通过像素颜色查找像素位置

问题描述 投票:0回答:1

该函数的目的是通过指定像素颜色查找像素的坐标。该函数现在处理屏幕分辨率的 1/20,这个速度至少是可以忍受的。使用这个系统,准确性会受到很大影响。

POINT FindColor(BYTE r, BYTE g, BYTE b) { 
    HDC hDC = GetDC(NULL);
    int width = GetDeviceCaps(hDC, HORZRES); 
    int height = GetDeviceCaps(hDC, VERTRES); 
    int xStep = width / 20; 
    int yStep = height / 20; 
    for (int x = 0; x < width; x += xStep) { 
        for (int y = 0; y < height; y += yStep) { 
            COLORREF color = GetPixel(hDC, x, y); 
            BYTE pixelR = GetRValue(color); 
            BYTE pixelG = GetGValue(color); 
            BYTE pixelB = GetBValue(color); 
            if (pixelR == r && pixelG == g && pixelB == b) { 
                ReleaseDC(NULL, hDC);
                POINT p;
                p.x = x;
                p.y = y;
                return p; 
            } 
        } 
    } 
    ReleaseDC(NULL, hDC); 
    POINT p = { -1, -1 }; 
    return p; 
}

目标是处理每个像素,但找到颜色需要超过 1 秒。

可能最好的解决方案是通过大量线程,但我不知道如何形式化它。

问题是,如何优化代码,使代码处理所有像素进行检查,以确保准确性,但查找颜色的速度约为 1 秒?

c++ winapi
1个回答
0
投票

以下代码只需 58 毫秒即可检查整个图像,无需平铺或单独的线程。

HBITMAP GetScreenBmp(HDC hdc) {
    // Get screen dimensions
    int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

    // Create compatible DC, create a compatible bitmap and copy the screen 
using BitBlt()
    HDC hCaptureDC = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
    BOOL bOK = BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight, hdc, 0, 0, SRCCOPY | CAPTUREBLT);

    SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
    DeleteDC(hCaptureDC);
    return hBitmap;
}

POINT FindColor(BYTE r, BYTE g, BYTE b) {
    const COLORREF findColorRef = RGB(r, g, b);

    HDC hDC = GetDC(NULL);
    int width = GetDeviceCaps(hDC, HORZRES);
    int height = GetDeviceCaps(hDC, VERTRES);
    HBITMAP hBitmap = GetScreenBmp(hDC);

    BITMAPINFO MyBMInfo = { 0 };
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

    // Get the BITMAPINFO structure from the bitmap
    if (0 == GetDIBits(hDC, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
        cout << "error" << endl;
    }

    // create the bitmap buffer
    BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

    // Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
    // necessary to read the color table - you might not want this.
    MyBMInfo.bmiHeader.biCompression = BI_RGB;

    // get the actual bitmap buffer
    if (0 == GetDIBits(hDC, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
        cout << "error2" << endl;
    }

    const int bufferSize = width * height*3;

    for (int y = 0; y < height; ++y)
    {
        for (int x = 0; x < width; ++x)
        {

            if ((lpPixels[4 * ((y * width) + x) + 2] == r) && (lpPixels[4 * ((y * width) + x) + 1] == g) && (lpPixels[4 * ((y * width) + x) ] == b))

            {
                ReleaseDC(NULL, hDC);
                POINT p;
                p.x = x;
                p.y = y;
                return p;
                }
            }
        }

        ReleaseDC(NULL, hDC);
        POINT p = { -1, -1
    };
    return p;
}
© www.soinside.com 2019 - 2024. All rights reserved.