怎么用QT+OpenCV实现录屏功能
发表于:2024-11-27 作者:千家信息网编辑
千家信息网最后更新 2024年11月27日,这篇"怎么用QT+OpenCV实现录屏功能"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这
千家信息网最后更新 2024年11月27日怎么用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安全错误
数据库的锁怎样保障安全
方舟服务器手游多少钱一个
眯莫服务器
自建frp服务器 无固定ip
湖北金税盘安全服务器
患者数据库营销方案
联想售后24小时电话服务器
北京软件开发者企业
移动互联网应用软件开发答案
服务器的根节点id
二级数据库和三级数据库关系
网络安全公司的优势
租用服务器好还是放云平台好
网络安全朗诵主持词
浙江软件开发公司注册
数据库文件属性中安全中没有
数据库模型优化的方式
软件开发模型几种类型比较好
湖南网络安全应急中心
网络安全漫画手绘图片海报
his 虚拟服务器
服务器页面
平阳科安网络技术服务工作室
cc2530软件开发情况
qt开源音处理软件开发
数据库为何需要事务提交
数据库inner
百合兽数据库
vps 如何创建数据库
怎么测试服务器ping值
怎么修改vs2015数据库