Cómo capturar el escritorio en OpenCV (es decir, convertir un bitmap en un Mat)?

Quiero usar OpenCV para procesar mi escritorio como si fuera una transmisión de video.
Estoy familiarizado con OpenCV.
No estoy familiarizado con la API de Windows. Me doy cuenta de que hay otras maneras de capturar la pantalla, pero a los fines de mi pregunta, necesito que se haga usando OpenCV.

Aquí está mi código (super ingenuo):

HWND hDesktopWnd; HDC hDesktopDC; hDesktopWnd=GetDesktopWindow(); hDesktopDC=GetDC(hDesktopWnd); // get the height and width of the screen int height = GetSystemMetrics(SM_CYVIRTUALSCREEN); int width = GetSystemMetrics(SM_CXVIRTUALSCREEN); // create a bitmap HBITMAP hbDesktop = CreateCompatibleBitmap( hDesktopDC, width, height); Mat src(height,width,CV_8UC4); src.data = (uchar*)hbDesktop; imshow("output",src); //fails :( 

Hay preguntas similares en StackOverflow, pero son para el viejo estilo OpenCV o para el sistema operativo Android.
Estoy en Windows 7 64x
Opencv 2.4.3

Gracias a todos los que puedan responder esta pregunta.

Después de MUCH bash y error, logré escribir una función para hacerlo. aquí está para cualquier otra persona que lo desee:

 #include "stdafx.h" #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include  #include  #include  #include  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/2; //change this to whatever size you want to resize to width = windowsize.right/2; 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; } 

Una mejor forma de hacerlo es hacerlo al asignar memoria a los píxeles solo una vez. entonces la única copia hecha aquí es la que hizo BitBlt

enter image description here

 int main() { int x_size = 800, y_size = 600; // <-- Your res for the image HBITMAP hBitmap; // <-- The image represented by hBitmap Mat matBitmap; // <-- The image represented by mat // Initialize DCs HDC hdcSys = GetDC(NULL); // Get DC of the target capture.. HDC hdcMem = CreateCompatibleDC(hdcSys); // Create compatible DC void *ptrBitmapPixels; // <-- Pointer variable that will contain the potinter for the pixels // Create hBitmap with Pointer to the pixels of the Bitmap BITMAPINFO bi; HDC hdc; ZeroMemory(&bi, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = x_size; bi.bmiHeader.biHeight = -y_size; //negative so (0,0) is at top left bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; hdc = GetDC(NULL); hBitmap = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, &ptrBitmapPixels, NULL, 0); // ^^ The output: hBitmap & ptrBitmapPixels // Set hBitmap in the hdcMem SelectObject(hdcMem, hBitmap); // Set matBitmap to point to the pixels of the hBitmap matBitmap = Mat(y_size, x_size, CV_8UC4, ptrBitmapPixels, 0); // ^^ note: first it is y, then it is x. very confusing // * SETUP DONE * // Now update the pixels using BitBlt BitBlt(hdcMem, 0, 0, x_size, y_size, hdcSys, 0, 0, SRCCOPY); // Just to do some image processing on the pixels.. (Dont have to to this) Mat matRef = matBitmap(Range(100, 200), Range(100, 200)); // y1 y2 x1 x2 bitwise_not(matRef, matRef); // Invert the colors in this x1,x2,y1,y2 // Display the results through Mat imshow("Title", matBitmap); // Wait until some key is pressed waitKey(0); return 0; } 

Tenga en cuenta que no se maneja ningún error aquí para que sea fácil de entender, ¡pero tiene que hacer un manejo de errores en su código!

Espero que esto ayude