怎么用QT+OpenCV实现录屏功能
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇"怎么用QT+OpenCV实现录屏功能"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这
千家信息网最后更新 2026年11月02日怎么用QT+OpenCV实现录屏功能
这篇"怎么用QT+OpenCV实现录屏功能"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"怎么用QT+OpenCV实现录屏功能"文章吧。
(1)获取窗体界面
QScreen类有一个grabWindow函数,可以用来获取窗体的画面,这个函数使用很简单,就是传入窗体句柄和要截取的坐标。但是这个函数有一个缺陷,它是通过截取桌面画面的方式,而不是通过
窗体获取界面,所以当你的窗体被其他窗体遮挡时,就无法截取完整的窗体界面,如果你是要录制整个桌面画面,那用这个函数就可以了,下面的方法调用GDI函数来实现,即使窗体被遮挡时仍然能够获取到完整界面,但是窗体最小化时也一样无法获取。
/** 函数功能:获取窗体指定窗体图像* 参 数:hd:窗体句柄* pm:保存获取到的图片* x:截取的起始x坐标,* y:截取的起始y坐标,* w:截取的宽度* h:截取的高度*/bool GetGDIBitmap(HWND hd,QPixmap &pm, int x, int y, int w, int h){ if(hd==NULL) return false; HDC hDC; hDC=GetDCEx(hd,NULL,DCX_PARENTCLIP ); HDC hMemDC; //内存缓冲设备环境 HBITMAP hbmMem,hbmOld; //内存缓冲设备环境中的位图 RECT rc; rc.left=x; rc.top=y; rc.right=x+w; rc.bottom=y+h; //判断边境值 RECT clientrc; ::GetClientRect(hd,&clientrc); int xc =0; int cx =0; int cy =0; if(rc.bottom>clientrc.bottom || rc.bottom<0) rc.bottom=clientrc.bottom; if(rc.right>clientrc.right || rc.right<0) rc.right=clientrc.right; // 24位图的BITMAPINFO BITMAPINFO *pBITMAPINFO = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER)); memset(pBITMAPINFO, 0, sizeof(BITMAPINFOHEADER)); BITMAPINFOHEADER *pInfo_Header = (BITMAPINFOHEADER *)pBITMAPINFO; pInfo_Header->biSize = sizeof(BITMAPINFOHEADER); pInfo_Header->biWidth = rc.right - rc.left; pInfo_Header->biHeight = (rc.bottom - rc.top); pInfo_Header->biPlanes = 1; pInfo_Header->biBitCount = 24; pInfo_Header->biCompression = BI_RGB; hMemDC=CreateCompatibleDC(hDC); //创建内存兼容设备环境 //创建内存兼容位图 hbmMem=CreateCompatibleBitmap(hDC,pInfo_Header->biWidth,pInfo_Header->biHeight); hbmOld=(HBITMAP)SelectObject(hMemDC,hbmMem); //将内存设备环境中的内容绘制到物理设备环境 hDC BitBlt(hMemDC,0,0,pInfo_Header->biWidth,pInfo_Header->biHeight,hDC,cx+rc.left,xc+cy+rc.top,CAPTUREBLT|SRCCOPY); HBITMAP hBitmap=(HBITMAP)SelectObject(hMemDC,hbmOld); // 获得数据buf DWORD bufSize=(pInfo_Header->biWidth * 3 + 3) / 4 * 4 * pInfo_Header->biHeight; BYTE * pBuffer = new BYTE[bufSize]; int aHeight=pInfo_Header->biHeight; if(::GetDIBits(hMemDC, hBitmap, 0, aHeight, pBuffer,pBITMAPINFO, DIB_RGB_COLORS) == 0) { return false; } bool bret=BitmapToPixmap(hBitmap,pm); ReleaseDC(hd,hDC); //释放资源 DeleteObject(hbmMem); DeleteObject(hbmOld); DeleteDC(hMemDC); free(pBITMAPINFO); ::DeleteObject(hBitmap); delete [] pBuffer; return bret;} /** 函数功能:将bitmap转为QPixmap*/bool BitmapToPixmap(HBITMAP hBitmap, QPixmap &pm){ HDC hDC; //设备描述表 int iBits; //当前显示分辨率下每个像素所占字节数 WORD wBitCount; //位图中每个像素所占字节数 //定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数 DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize; BITMAP Bitmap; //位图属性结构 BITMAPFILEHEADER bmfHdr; //位图文件头结构 BITMAPINFOHEADER bi; //位图信息头结构 LPBITMAPINFOHEADER lpbi; //指向位图信息头结构 HANDLE hDib, hPal; HPALETTE hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄 //计算位图文件每个像素所占字节数 hDC = CreateDC(L"DISPLAY",NULL,NULL,NULL); iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); DeleteDC(hDC); if (iBits <= 1) wBitCount = 1; else if (iBits <= 4) wBitCount = 4; else if (iBits <= 8) wBitCount = 8; else if (iBits <= 24) wBitCount = 24; else wBitCount = 24; //计算调色板大小 if (wBitCount <= 8) dwPaletteSize=(1<buffer; uchar *p=(uchar*)&bmfHdr; // 写入位图文件头 buffer.insert(buffer.end(),p,p+sizeof(BITMAPFILEHEADER)); // 写入位图文件其余内容 p=(uchar*)lpbi; buffer.insert(buffer.end(),p,p+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize); //清除 GlobalUnlock(hDib); GlobalFree(hDib); pm=QPixmap::fromImage(QImage::fromData(buffer.data(),buffer.size())); return true;} (2)录制画面
bool g_needstop =false;void Record(){ RECT rect; //获取窗体位置大小 GetWindowRect(hd,&rect); cv::Size frameSize; frameSize.width=rect.right-rect.left; frameSize.height=rect.bottom-rect.top; cv::VideoWriter VideoWriter; if(!VideoWriter.open("d:\\1.avi",CV_FOURCC('M', 'J', 'P', 'G'),40,frameSize)) return; while(!g_needstop) { QPixmap pm; GetGDIBitmap(hd,pm,0,0,frameSize.width,frameSize.height); VideoWriter.write(ImageToMat(pm.toImage())); } VideoWriter.release(); }Mat ImageToMat(QImage img,QString imgFormat){ if(img.isNull()) return Mat(); QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); img.save(&buffer,imgFormat.toLatin1().data()); _InputArray arrSrc(ba.data(), ba.size()); Mat mat = cv::imdecode(arrSrc, CV_LOAD_IMAGE_COLOR); return mat;}(3) 播放视频
void Play(){ cv::VideoCapture Capture; if(!Capture.open("d:\\1.avi")) return; Mat frame; //逐帧读取画面 while(Capture.read(frame)) { //转成QImage格式用于显示 QImage img = MatToImage(frame); emit Frame(img); QThread::msleep(40); } Capture.release(); emit PlayFinsh();}QImage MatToImage(Mat mat){ if(mat.type() == CV_8UC1) { QImage image(mat.cols, mat.rows, QImage::Format_Indexed8); // Set the color table (used to translate colour indexes to qRgb values) image.setColorCount(256); for(int i = 0; i < 256; i++) { image.setColor(i, qRgb(i, i, i)); } // Copy input Mat uchar *pSrc = mat.data; for(int row = 0; row < mat.rows; row ++) { uchar *pDest = image.scanLine(row); memcpy(pDest, pSrc, mat.cols); pSrc += mat.step; } return image; } // 8-bits unsigned, NO. OF CHANNELS = 3 else if(mat.type() == CV_8UC3) { // Copy input Mat const uchar *pSrc = (const uchar*)mat.data; // Create QImage with same dimensions as input Mat QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); return image.rgbSwapped(); } else if(mat.type() == CV_8UC4) { qDebug() << "CV_8UC4"; // Copy input Mat const uchar *pSrc = (const uchar*)mat.data; // Create QImage with same dimensions as input Mat QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32); return image.copy(); } else { qDebug() << "ERROR: Mat could not be converted to QImage."; return QImage(); }}以上就是关于"怎么用QT+OpenCV实现录屏功能"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。
位图
窗体
内容
文件
内存
函数
设备
调色板
功能
像素
大小
字节
环境
画面
结构
句柄
界面
信息
坐标
就是
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网科技活动banner
互联网扶贫科技
美国互联网科技
嘟嘟瓜互联网科技
迪茉互联网科技
宜安科技 互联网金融
新浪科技互联网
互联网科技类展会
华脉科技工业互联网产品
浙江互联网科技研学营
互联网科技商业
宜昌元轩互联网科技有限公司
注册互联网科技公司经营范围大全
苏州铭阳互联网科技有限公司
民营互联网公司国防科技
深圳市罗太互联网科技有限公司
广西科技产业互联网是什么
北京军民互联网科技公司
互联网科技创新创业项目
六子台科技互联网展会
工业互联网科技新基建
远信互联网科技
时间互联网络科技
成都狮子座互联网科技
佰商互联网科技有限公司
联恩商钥互联网科技有限公司
科技大学互联网专业好不好
山东子淼互联网科技有限公司
小米互联网科技园入驻
广东工业互联网大赛深圳学泰科技