這個問題類似於this one,特別是this one但我期望的輸出是不同的。我試圖使用opencv捕獲桌面到視頻。首選的輸出是使用divx編碼的avi文件。一般來說,我對opencv和位圖編程是新手。使用opencv從幀創建一個divx編碼的AVI
作爲第一步,爲了確保divx編解碼器存在,我創建了一個純色(黃色)的單幀(cv :: Mat),並將100次寫入視頻文件,如下所示:
int main(int argc, char* argv[])
{
cv::Mat frame(1200, 1920, CV_8UC3, cv::Scalar(0, 50000, 50000));
cv::VideoWriter* videoWriter = new cv::VideoWriter(
"C:/videos/desktop.avi",
CV_FOURCC('D','I','V','3'),
5, cv::Size(1920, 1200), true);
int frameCount = 0;
while (frameCount < 100)
{
videoWriter->write(frame);
::Sleep(100);
frameCount++;
}
delete videoWriter;
return 0;
}
這完美的作品 - 創建視頻文件,可以在我贏得10機VLC,Windows媒體播放器或電影&電視應用上播放。它是純黃色的100幀,但它表明視頻正在正確創建。
下一步:用上面代碼中的虛擬cv :: Mat框架替換桌面的一系列屏幕截圖。我使用GetDesktopWindow()獲得桌面窗口的句柄,然後使用函數hwnd2mat(取自this SO問題 - 謝謝!)將從桌面句柄獲取的位圖轉換爲可以寫入我的視頻的cv :: Mat。
我拷貝了hwnd2mat函數,但我沒有縮放圖像 - 桌面位圖已經是1920x1200,而且我創建的cv :: Mat是CV_8UC3而不是CV_8UC4(CV_8UC4導致我的應用程序崩潰)。
下面的代碼,包括hwnd2mat重印:
int main(int argc, char* argv[])
{
cv::VideoWriter* videoWriter = new cv::VideoWriter(
"C:/videos/desktop.avi",
CV_FOURCC('D','I','V','3'),
5, Size(1920, 1200), true);
int frameCount = 0;
while (frameCount < 100)
{
HWND hDsktopWindow = ::GetDesktopWindow();
cv::Mat frame = hwnd2mat(hDsktopWindow);
videoWriter->write(frame);
::Sleep(100);
frameCount++;
}
delete videoWriter;
return 0;
}
cv::Mat hwnd2mat(HWND hwnd)
{
HDC hwindowDC, hwindowCompatibleDC;
int height, width, srcheight, srcwidth;
HBITMAP hbwindow;
cv::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_8UC3);
// create a bitmap
hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
bi.biSize = sizeof(BITMAPINFOHEADER);
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);
GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
// avoid memory leak
DeleteObject(hbwindow); DeleteDC(hwindowCompatibleDC); ReleaseDC(hwnd,hwindowDC);
return src;
}
這樣做的結果是生成視頻文件,並且可以無差錯進行播放,但它只是純灰色。似乎桌面的位圖沒有正確地複製到cv :: Mat框架中。我已經嘗試了BITMAPINFOHEADER中的數十億個值的組合,但沒有任何效果,我不知道我在做什麼要誠實。我知道opencv有轉換功能,但我甚至不知道我想要轉換爲/來自哪裏。
任何幫助表示讚賞!