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

效果如下:

相关推荐
Han.miracle1 小时前
数据结构——二叉树的从前序与中序遍历序列构造二叉树
java·数据结构·学习·算法·leetcode
mit6.8243 小时前
前后缀分解
算法
你好,我叫C小白3 小时前
C语言 循环结构(1)
c语言·开发语言·算法·while·do...while
寂静山林6 小时前
UVa 10228 A Star not a Tree?
算法
Neverfadeaway6 小时前
【C语言】深入理解函数指针数组应用(4)
c语言·开发语言·算法·回调函数·转移表·c语言实现计算器
Madison-No77 小时前
【C++】探秘vector的底层实现
java·c++·算法
Swift社区7 小时前
LeetCode 401 - 二进制手表
算法·leetcode·ssh
派大星爱吃猫7 小时前
顺序表算法题(LeetCode)
算法·leetcode·职场和发展
liu****7 小时前
8.list的模拟实现
linux·数据结构·c++·算法·list
地平线开发者8 小时前
征程 6 | 征程 6 工具链如何支持 Matmul/Conv 双 int16 输入量化?
算法·自动驾驶