を使用してフレームからdivxエンコードされたAVIを作成するこの質問はthis oneと似ていますが、特にthis oneと似ていますが、希望する出力が異なります。私はopencvを使ってビデオをデスクトップにキャプチャしようとしています。好ましい出力は、divxエンコーディングのaviファイルです。私はopencvとビットマッププログラミングには一般的に新しいです。opencv
最初の手順として、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;
}
これは完璧に動作します - ビデオファイルが作成され、VLC、WindowsのMedia Playerや映画&テレビアプリと私の10勝のマシン上で再生することができます。これは100フレームの黄色ですが、ビデオが正しく作成されていることを示しています。
次の手順:上記のコードのダミーcv :: Matフレームをデスクトップの一連のスクリーンショットで置き換えます。私はGetDesktopWindow()を使用してデスクトップウィンドウへのハンドルを取得し、hwnd2mat(this SOから質問しました - ありがと!)を使用して、デスクトップハンドルから取得したビットマップを自分のビデオに書き込むことができるcv :: Matに変換します。
デスクトップのビットマップはすでに1920x1200であり、CV_8UC4ではなくCV_8UC3がCV_8UC3で作成されています(CV_8UC4がクラッシュするようになりました)以外は、hwnd2mat関数をそのままコピーしました。
はここ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が変換関数を持っていることを知っていますが、私は実際に私が/から変換しようとしているものは実際にはわかりません。