第12课 实现桌面与摄像头叠加

在上一节,我们实现了桌面捕获功能,并成功把桌面图像和麦克风声音发送给对方。在实际应用中,有时候会需要把桌面与摄像头图像叠加在一起发送,这节课我们就来看下如何实现这一功能。

1.备份与修改

备份demo11并修改demo11为demo12.

2.用新队列存放叠加前的图像数据

修改原函数capCam和capScr,用新的inCamQue和inScrQue存放摄像头和桌面图像Mat:

cpp 复制代码
int fmle::capCam() {

	videoCap.open(0);
	cv::Mat camMat;
	while (true)
	{

		if (!videoCap.isOpened()){
			Sleep(1);
			continue;
		}

		BOOL ifSuccess = videoCap.read(camMat);

		if (camMat.empty())
		{
			Sleep(1);
			continue;
		}
		if (camMat.cols != backWidth || camMat.rows != backHeight){
			resize(camMat, camMat, cv::Size(backWidth, backHeight));
		}
		if (!camMat.empty()){			
			EnterCriticalSection(&videoQueLock);
			tmpVideoQueObj.type = 1;
			tmpVideoQueObj.tmpMat = camMat;
			tmpVideoQueObj.dataLen = camMat.cols*camMat.rows * 3;
			inCamQue.push(tmpVideoQueObj);
			if (inCamQue.size() >videoDataArrNum){
				inCamQue.front().dataLen = 0;
				inCamQue.front().tmpMat.release();
				inCamQue.front().dataLen = NULL;
				inCamQue.pop();
			}
			LeaveCriticalSection(&videoQueLock);


		}
		Sleep(40);
	}
	camMat.release();

	return 0;
}

int fmle::capScr(){
    
    HWND hwnd = GetDesktopWindow();
    cv::Mat scrMat;
    while (true)
    {
        scrMat = hwndToMat(hwnd);        
        if (scrMat.cols != backWidth || scrMat.rows != backHeight){
            resize(scrMat, scrMat, cv::Size(backWidth, backHeight));
        }

        if (scrMat.data&&!scrMat.empty()){        
            cvtColor(scrMat, scrMat, CV_BGRA2BGR);
            //mainDlg->drawMatOfPub(scrMat);
            EnterCriticalSection(&videoQueLock);
            tmpVideoQueObj.type = 1;
            tmpVideoQueObj.tmpMat = scrMat;
            tmpVideoQueObj.dataLen = scrMat.cols*scrMat.rows * 3;
            inScrQue.push(tmpVideoQueObj);
            if (inScrQue.size() >videoDataArrNum){
                inScrQue.front().dataLen = 0;
                inScrQue.front().tmpMat.release();
                inScrQue.front().dataLen = NULL;
                inScrQue.pop();
            }
            LeaveCriticalSection(&videoQueLock);

        }
        Sleep(40);
    }

    scrMat.release();    
    return 0;
}

3.分别从桌面和摄像头队列取数据并叠加

新建一线程,调用mixVideo实现桌面和摄像头图像的叠加

cpp 复制代码
int fmle::mixVideo(){

    cv::Mat camMat, scrMat, imageROI;
    while (true){
        if (inScrQue.size() > 0 && inCamQue.size() > 0){
            EnterCriticalSection(&videoQueLock);
            camMat = inCamQue.front().tmpMat.clone();
            resize(camMat, camMat, cv::Size(120, 80));
            scrMat = inScrQue.front().tmpMat.clone();
            if (!camMat.empty() && !scrMat.empty()){
                imageROI = scrMat(cv::Rect(0, 0, camMat.cols, camMat.rows));
                addWeighted(imageROI, 0, camMat, 1, 0.0, imageROI);
                mainDlg->drawMatOfPub(scrMat);
            }
            camMat.release();
            scrMat.release();
            imageROI.release();
            LeaveCriticalSection(&videoQueLock);
        }
        Sleep(40);
    }
    return 0;
}

4.调试运行

效果如下:

相关推荐
JieE21221 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack201 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树1 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2122 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2122 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术2 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦2 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050732 天前
(一)小红的数组操作
算法·编程语言
RTC实战笔记2 天前
Android 实时音视频接入教程:媒体补充增强信息(SEI)
音视频·媒体·rtc