基于OpenCV创建视频会议虚拟背景

小白学视觉

共 1873字,需浏览 4分钟

 ·

2020-09-20 10:52


点击上方小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本期我们将使用Python和OpenCV为视频会议创建虚拟背景。

虚拟背景是当前远程工作的员工中的热门话题之一。由于Covid-19的流行,许多人必须通过视频通话以便继续工作。很多视频会议的软件可以设置虚拟背景,以便用户建立更友好的氛围来接听这些电话。

作为一名程序员,当我们第一次使用这样的虚拟背景时自然很感兴趣。我们都想知道它是如何工作的,可以自己建立这样的虚拟背景吗?

接下来,我们将尝试使用PythonOpenCV使用计算机视觉技术构建虚拟背景的基本方法。(虽然效果并不是很好~)

介绍

我们的目的是拍摄视频,尝试弄清楚视频的背景和前景,删除背景部分,并用图片(虚拟背景)代替。因为在此项目中,我们将使用简单的方法,假设前景通常具有与背景不同的颜色。首先,让我们看看我们的工具是什么。

计算机视觉

计算机视觉是一个跨学科领域,涉及计算机如何处理和(或)理解图像和视频。说这是一个跨学科的领域,因为它借鉴了不同学科(计算机科学,代数,几何等)的许多概念,并将它们组合起来以解决许多不同而复杂的任务,例如对象跟踪对象检测, 对象识别,图片和视频中的对象细分

OpenCV

OpenCV是一个用于解决计算机视觉任务的库。它是开源的,可用于多种编程语言,包括Python和C ++。它具有大量的计算机视觉功能,其中一些基于数学和统计方法,而另一些则基于机器学习。

建立虚拟背景

我为此尝试的方法如下。我将显示每个步骤的代码片段,并在本文结尾处,您将获得完整的代码。

1. 导入依赖

import numpy as npimport cv2

2.从本地环境加载视频并初始化数据

ap = cv2.VideoCapture('video6.mp4')ret = TrueframeCounter = 0previousFrame = NonenextFrame = Noneiterations = 0

3.从本地环境加载替代背景图像

backgroundImage = cv2.imread("image1.jpg")

4.逐帧分割视频

while (ret):ret, frame = cap.read()

5.每隔两帧拍摄一次

if frameCounter % 2 == 1:           nextFrame = frame        if frameCounter % 2 == 0:           frameCounter = 0           previousFrame = frame       frameCounter = frameCounter + 1           iterations = iterations + 1

6.找到两个帧之间的绝对差并将其转换为灰度->获得蒙版

if iterations > 2:  diff = cv2.absdiff(previousFrame, nextFrame)  mask = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)

每个图像都由像素组成,我们可以将其想象为具有行和列的2D矩阵,并且矩阵中的每个单元格都是图像中的像素(当然,对于彩色图像,我们拥有的尺寸比2大,但为简单起见,可以忽略)。

我们通过在第一个图像中逐个像素移动(因此在第一矩阵中一个单元一个像素)并从另一个图像中替换对应的像素(因此从另一个矩阵中替换对应的像素)来获得差异。

现在的诀窍是:如果在两帧之间,像素没有被修改,那么结果当然是0两帧之间的像素如何变化?如果视频是完全静态的(图像中没有任何动静),则所有像素的每一帧之间的差将为0,因为没有任何更改。但是,如果某物在图像中移动,那么我们可以通过检测像素差异来识别某物在图像中的移动位置。我们可以假设,在视频会议中,移动的事物位于前台(即您),而静态部分是背景。

那么0到底有什么重要呢?图像将为每个像素显示为0的黑色,我们将利用这一优势。

7.找到蒙版中超出阈值的单元格-我选择3作为阈值,当然也可以使用不同的值。较大的值将从背景中删除更多内容,但也可能从前景中删除更多内容

th = 3isMask = mask > thnonMask = mask <= th

8.创建一个空白图像(每个单元格为0),其大小为两个框架中任何一个的大小

result = np.zeros_like(nextFrame, np.uint8)

9.调整背景图像的大小,使其具有与框架相同的大小

resized = cv2.resize(backgroundImage, (result.shape[1], result.shape[0]), interpolation = cv2.INTER_AREA)

10.对于蒙版中大于阈值的每个单元,请从原始帧进行复制

result[isMask] = nextFrame[isMask]000000000000

11.对于蒙版中低于阈值的每个单元,请从替代背景图像进行复制

result[nonMask] = resized[nonMask]

12.将结果框保存到本地环境

cv2.imwrite("output" + str(iterations) + ".jpg", result)

结果与结论

那么结果如何呢?老实说,我对结果感到有些失望。然后,我做了更多的研究,其原因变得更加明显。为此,您需要一种更高级的方法,并且大公司在此类问题上投入了大量资源也就不足为奇了。

这是我尝试的视频的屏幕截图。这基本上是我的手在墙前移动的视频。

虚拟背景Python和OpenCV教程-输入

这是输出图像的屏幕截图。作为背景,我在罗马尼亚的拉斯诺夫使用了我的照片。

虚拟背景Python和OpenCV教程-输出

结果并不满意,但是我们也从这个项目中学到的东西。

创建虚拟背景的其他方法

如果认为问题非常复杂,并且需要的智能水平,那么答案可能是机器学习。

已有深度学习模型可以执行此类任务。但是,这样的模型需要训练大量的数据集和大量的处理能力,在撰写本文时,我还没有这些能力做这种尝试。这种深度学习模型要解决的任务称为图像分割。

另一种方法是计算机视觉方法,用于查找相机和图像中的对象之间的距离。然后,建立一个阈值,以将前景与背景分开。之后,可以使用与移除背景相同的蒙版,并引入一个新的蒙版。

交流群


欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~


浏览 61
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报