第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.调试运行

效果如下:

相关推荐
南宫生39 分钟前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步1 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara2 小时前
函数对象笔记
c++·算法
泉崎2 小时前
11.7比赛总结
数据结构·算法
你好helloworld2 小时前
滑动窗口最大值
数据结构·算法·leetcode
MediaTea2 小时前
Pr 视频过渡:沉浸式视频 - VR 色度泄漏
音视频·vr
LNTON羚通2 小时前
算法定制LiteAIServer摄像机实时接入分析平台烟火检测算法的主要功能
音视频·视频监控
AI街潜水的八角3 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple3 小时前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少3 小时前
数据结构——线性表与链表
数据结构·c++·算法