这个问题类似于
this one
特别是
this one
但我想要的输出是不同的。我正在尝试使用opencv将桌面捕获为视频。首选输出是具有divx编码的avi文件。我是opencv和位图编程的新手。
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;
}
这工作完美-视频文件被创建,可以在我的Win 10机器上播放VLC,Windows Media Player或电影&电视应用程序。它是100帧纯黄色,但它显示视频正在正确创建。
下一步:用一系列桌面截图替换上面代码中的虚拟cv::Mat框架。我使用获得桌面窗口的句柄
GetDesktopWindow()
,然后使用函数hwnd2mat(取自
this
所以这个问题-谢谢将从桌面句柄获得的位图转换为cv::Mat,以便写入视频。
我逐字复制了hwnd2mat函数,只是我没有缩放图像-桌面位图已经是1920x1200,而且我创建的cv::Mat是cv_8UC3而不是cv_8 UC4(cv_9UC4导致我的应用程序崩溃)。
以下是代码,包括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框架中。我在BitMapInfo标头中尝试了无数个值的组合,但没有任何效果,老实说,我不知道我在做什么。我知道opencv有转换功能,但我甚至不知道我要转换什么。