網站首頁 編程語言 正文
本文實例為大家分享了OpenCV實現簡單錄屏功能的具體代碼,供大家參考,具體內容如下
OpenCV中VideoCapture和VideoWriter用于讀寫視頻文件,這里的錄屏功能用到VideoWriter,用于將捕獲的屏幕的每一幀數據保存到視頻文件。
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;//每行字節數必須是4字節的整數倍 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為屏幕的像素顏色數據,下列代碼將lpbitmap作為一幀寫到視頻中(假設VideoWriter為已正常打開的VideoWriter實例)
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;
因為lpbitmap中的數據是從左下角到右上角排列,而視頻幀圖像的數據是從左上角到右下角排列,所以要將數據按行上下翻轉,即lpbitmap第一行對應視頻圖像的最后一行。另外BMP圖像數據每行的字節數必須是4字節的整數倍,而寫入視頻的Mat數據沒有這個要求,即每行數據大小是圖像實際寬度乘以每個顏色占用的字節數,所以實際每行拷貝的數據是width*3節字。
下面是一段測試代碼,這里只錄制100幀,實際使用中可通過命令行參數、快捷鍵或按鈕等自行決定開始和結束時間,幀率這里也設為固定的25,其實也應該根據具體形況設定合適的值。最后別忘了將opencv_ffmpegXXX.dll文件放到可執行文件目錄下。
#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; }
原文鏈接:https://blog.csdn.net/yb0022/article/details/100893722
相關推薦
- 2022-06-01 C語言的動態內存管理你了解嗎_C 語言
- 2022-08-16 C++超詳細講解友元與內部類_C 語言
- 2022-09-03 一起聊聊C++中的特殊成員函數_C 語言
- 2024-02-29 UNI-APP頁面跳轉時(uni.navigateTo),參數傳遞
- 2022-06-06 Array.prototype.myfindIndex
- 2022-03-30 c語言static關鍵字用法詳解_C 語言
- 2022-11-01 go語言中for?range使用方法及避坑指南_Golang
- 2022-08-22 如何使用Python?Matplotlib繪制條形圖_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支