Захват рабочего стола OPENCV, часть II

Продолжение в предыдущем посте отсюда OPENCV Destop Capture и этот hwnd2mat метод захвата рабочего стола в качестве источника в opencv заключается в создании растрового изображения из изображения экрана с помощью этой функции hwnd2mat. сделано. эта функция уже создает растровое изображение из изображения на экране. Но она дает странный эффект, например, трейлинг внутри видео, мне просто нужен обычный источник видео, например этот . Я уже пытался найти причину этого, но я больше не знаю.

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

person mas bro    schedule 19.04.2016    source источник
comment
странный эффект выглядит следующим образом: youtube.com/watch?v=RQePoFEUS3A&feature=youtu .be, не могли бы вы рассказать мне, что случилось?   -  person mas bro    schedule 19.04.2016
comment
так что вы не хотите захватить весь экран, а только одно окно? Очевидно, что если вы захватываете весь экран, вы снова захватываете выходное изображение, что приводит к эффекту бесконечного зеркала. Вместо GetDesktopWindow вы должны получить доступ/найти дескриптор окна, которое хотите захватить.   -  person Micka    schedule 19.04.2016
comment
@Micka хорошо, я понял, я должен найти дескриптор окна, которое я хочу захватить, но что это вместо GetDesktopWindow ?   -  person mas bro    schedule 19.04.2016
comment
какое окно вы хотите захватить? Если вы знаете имя, используйте FindWindow msdn.microsoft.com/de-de/library/windows/desktop/ или, может быть, вы можете использовать GetActiveWindow, если вам удастся сделать нужное окно активным. Если вы хотите вместо этого захватить весь экран, возможно, вы можете скрыть окно вывода перед вызовом GetDesktopWindow и снова отобразить его после этого.   -  person Micka    schedule 19.04.2016
comment
вот способ скрыть ваше окно в delphi: stackoverflow.com/questions/22430706/, возможно, вы сможете это адаптировать.   -  person Micka    schedule 19.04.2016
comment
@Micka, я думаю, я выберу окно, которое я хочу захватить, скажем, я хочу захватить первую вкладку www.youtube.com из Google Chrome, так как мне написать это: HWND WINAPI FindWindow( _In_opt_ LPCTSTR lpClassName, _In_opt_ LPCTSTR lpWindowName );   -  person mas bro    schedule 19.04.2016
comment
Я не эксперт по Windows API, но, возможно, вы можете найти больше информации в таких вопросах/ответах: stackoverflow.com/questions/19705797/ и общие руководства по API Windows о том, как использовать FindWindow и/или как использовать дескрипторы Windows.   -  person Micka    schedule 19.04.2016
comment
@Мика Наконец-то! до сих пор 2:31, я понимаю, о чем идет речь, ты прав, Мика!, спасибо, чувак! ты мой герой.! Я получаю результат, который я хочу! мало того, теперь я понимаю логику оконных ручек!! :)   -  person mas bro    schedule 19.04.2016
comment
это приятно слышать!   -  person Micka    schedule 19.04.2016


Ответы (1)


Использование GetDesktopWindow() создаст эффект бесконечного зеркала, вместо этого, используя то окно, которое вы хотите захватить, и я использую FindWindowEx() и использую Spy++, чтобы найти, какое окно вы хотите захватить, это должно работать. но конечно дело пойдет к следующему багу :).

person mas bro    schedule 20.04.2016