OpenCV實(shí)現(xiàn)簡(jiǎn)單錄屏功能
本文實(shí)例為大家分享了OpenCV實(shí)現(xiàn)簡(jiǎn)單錄屏功能的具體代碼,供大家參考,具體內(nèi)容如下
OpenCV中VideoCapture和VideoWriter用于讀寫視頻文件,這里的錄屏功能用到VideoWriter,用于將捕獲的屏幕的每一幀數(shù)據(jù)保存到視頻文件。
VideoWriter寫視頻文件的步驟
1、bool open(const String& filename, int fourcc, double fps,Size frameSize, bool isColor = true);
2、void write(InputArray image);或者VideoWriter& operator << (const Mat& image);
3、void release();
下列代碼用于獲取屏幕的截圖
int width = GetSystemMetrics(SM_CXSCREEN); int height = GetSystemMetrics(SM_CYSCREEN); HDC hdcScreen = GetDC(NULL); HDC hdcMemDC = CreateCompatibleDC(hdcScreen); HBITMAP hbmScreen = CreateCompatibleBitmap(hdcScreen, width, height); ? BITMAPINFO bi; bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = width; bi.bmiHeader.biHeight = height; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = 0; bi.bmiHeader.biXPelsPerMeter = 0; bi.bmiHeader.biYPelsPerMeter = 0; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; SelectObject(hdcMemDC, hbmScreen); int lineBytes = ((width * bi.bmiHeader.biBitCount + 31) / 32) * 4;//每行字節(jié)數(shù)必須是4字節(jié)的整數(shù)倍 int bmpSize = lineBytes * height; char* lpbitmap = new char[bmpSize]; BitBlt(hdcMemDC, 0, 0, width, height, hdcScreen, 0, 0, SRCCOPY); GetDIBits(hdcMemDC, hbmScreen, 0, height, lpbitmap, &bi, DIB_RGB_COLORS);
lpbitmap為屏幕的像素顏色數(shù)據(jù),下列代碼將lpbitmap作為一幀寫到視頻中(假設(shè)VideoWriter為已正常打開(kāi)的VideoWriter實(shí)例)
cv::Mat bmpMat(height, width, CV_8UC3);
for (int i = 0; i < height; i++)
{
? ? int srcIndex = (height-i-1) * lineBytes;
? ? int destIndex = i * width * 3;
? ? memcpy(&bmpMat.data[destIndex],&lpbitmap[srcIndex],width*3);
}
videoWriter.write(bmpMat);//或videoWriter << bmpMat;因?yàn)閘pbitmap中的數(shù)據(jù)是從左下角到右上角排列,而視頻幀圖像的數(shù)據(jù)是從左上角到右下角排列,所以要將數(shù)據(jù)按行上下翻轉(zhuǎn),即lpbitmap第一行對(duì)應(yīng)視頻圖像的最后一行。另外BMP圖像數(shù)據(jù)每行的字節(jié)數(shù)必須是4字節(jié)的整數(shù)倍,而寫入視頻的Mat數(shù)據(jù)沒(méi)有這個(gè)要求,即每行數(shù)據(jù)大小是圖像實(shí)際寬度乘以每個(gè)顏色占用的字節(jié)數(shù),所以實(shí)際每行拷貝的數(shù)據(jù)是width*3節(jié)字。
下面是一段測(cè)試代碼,這里只錄制100幀,實(shí)際使用中可通過(guò)命令行參數(shù)、快捷鍵或按鈕等自行決定開(kāi)始和結(jié)束時(shí)間,幀率這里也設(shè)為固定的25,其實(shí)也應(yīng)該根據(jù)具體形況設(shè)定合適的值。最后別忘了將opencv_ffmpegXXX.dll文件放到可執(zhí)行文件目錄下。
#include<windows.h>
#include"opencv2/opencv.hpp"
int main()
{
?
? ? cv::VideoWriter videoWriter;
? ? double fps = 25;
? ? int codec = cv::VideoWriter::fourcc('m', 'p', '4', 'v');
? ? int width = ?GetSystemMetrics(SM_CXSCREEN);
? ? int height = GetSystemMetrics(SM_CYSCREEN);
?
? ? time_t seconds = time(0);
? ? int s = seconds % 60;
? ? int m = (seconds % 3600) / 60;
? ? int h = (seconds % (3600 * 24)) / 3600 + 8;
? ? char timeBuf[128] = { 0 };
? ? sprintf_s(timeBuf, "CaptureScreen-%d-%d-%d.mp4", h, m, s);
? ? cv::String filePath = timeBuf;
? ? videoWriter.open(filePath, codec, fps, cv::Size(width, height), true);
? ? if (!videoWriter.isOpened())
? ? {
? ? ? ? return -1;
? ? }
?
? ? HDC hdcScreen = GetDC(NULL);
? ? HDC hdcMemDC = CreateCompatibleDC(hdcScreen);
? ? HBITMAP hbmScreen = CreateCompatibleBitmap(hdcScreen, width, height);
?
? ? BITMAPINFO bi;
? ? bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
? ? bi.bmiHeader.biWidth = width;
? ? bi.bmiHeader.biHeight = height;
? ? bi.bmiHeader.biPlanes = 1;
? ? bi.bmiHeader.biBitCount = 24;
? ? bi.bmiHeader.biCompression = BI_RGB;
? ? bi.bmiHeader.biSizeImage = 0;
? ? bi.bmiHeader.biXPelsPerMeter = 0;
? ? bi.bmiHeader.biYPelsPerMeter = 0;
? ? bi.bmiHeader.biClrUsed = 0;
? ? bi.bmiHeader.biClrImportant = 0;
? ? SelectObject(hdcMemDC, hbmScreen);
?
? ? int lineBytes = ((width * bi.bmiHeader.biBitCount + 31) / 32) * 4;
? ? int bmpSize = lineBytes * height;
? ? char* lpbitmap = new char[bmpSize];
? ? cv::Mat bmpMat(height, width, CV_8UC3);
? ? for (int i=0;i<100;i++)
? ? {
? ? ? ? if (BitBlt(hdcMemDC, 0, 0, width, height, hdcScreen, 0, 0, SRCCOPY))
? ? ? ? {
? ? ? ? ? ? GetDIBits(hdcMemDC, hbmScreen, 0, height, lpbitmap, &bi, DIB_RGB_COLORS);
? ? ? ? ? ? for (int i = 0; i < height; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int srcIndex = (height-i-1) * lineBytes;
? ? ? ? ? ? ? ? int destIndex = i * width * 3;
? ? ? ? ? ? ? ? memcpy(&bmpMat.data[destIndex],&lpbitmap[srcIndex],width*3);
? ? ? ? ? ? }
? ? ? ? ? ? videoWriter.write(bmpMat);//videoWriter << bmpMat;
? ? ? ? }
? ? }
? ? delete[] lpbitmap;
? ? if (videoWriter.isOpened())
? ? {
? ? ? ? videoWriter.release();
? ? }
? ? return 0;
}以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于c++11與c風(fēng)格路徑拼接的速度對(duì)比
這篇文章主要介紹了關(guān)于c++11與c風(fēng)格路徑拼接的速度對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
error LNK2019: 無(wú)法解析的外部符號(hào) 問(wèn)題的解決辦法
error LNK2019: 無(wú)法解析的外部符號(hào) 問(wèn)題的解決辦法,需要的朋友可以參考一下2013-05-05
C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別
拷貝構(gòu)造函數(shù)和賦值函數(shù)非常容易混淆,本文主要介紹了C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04
C語(yǔ)言實(shí)現(xiàn)奇數(shù)階魔方陣的方法
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)奇數(shù)階魔方陣的方法,涉及數(shù)組及相關(guān)數(shù)學(xué)函數(shù)的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02
C語(yǔ)言修煉之路一朝函數(shù)思習(xí)得?模塊思維世間生上篇
函數(shù)是一組一起執(zhí)行一個(gè)任務(wù)的語(yǔ)句。每個(gè)?C?程序都至少有一個(gè)函數(shù),即主函數(shù)?main()?,所有簡(jiǎn)單的程序都可以定義其他額外的函數(shù)2022-03-03
C 語(yǔ)言編寫一個(gè)計(jì)算器界面(可視化界面和多功能)
今天給大家分享一個(gè)計(jì)算器功能,主要功能有加法減法乘除法求余功能,用戶可以在主菜單選擇需要計(jì)算的功能,接下來(lái)根據(jù)用戶輸入的數(shù)字進(jìn)行計(jì)算輸出結(jié)果,喜歡的朋友拿去用吧2021-06-06
C語(yǔ)言中的自定義類型之結(jié)構(gòu)體與枚舉和聯(lián)合詳解
今天我們來(lái)學(xué)習(xí)一下自定義類型,自定義類型包括結(jié)構(gòu)體、枚舉、聯(lián)合體,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考2022-06-06
C++ abs函數(shù)實(shí)際應(yīng)用詳解
本文我們來(lái)講C++的abs函數(shù)以及實(shí)戰(zhàn)運(yùn)用,C++中的abs函數(shù)。在C++中使用abs函數(shù)要注意存在兩種版本,一種是在stdlmb.h中定義的版本,另一個(gè)是在cmath頭文件中定義的。夷實(shí)上在stdlib.h文件是C的函數(shù),而cmath中的是C++版本2022-08-08

