前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于OpenCV创建视频会议虚拟背景

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

作者头像
小白学视觉
发布2020-09-22 15:21:18
3.4K1
发布2020-09-22 15:21:18
举报

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

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

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

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

介绍

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

计算机视觉

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

OpenCV

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

建立虚拟背景

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

1. 导入依赖

代码语言:javascript
复制
import numpy as np
import cv2

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

代码语言:javascript
复制
ap = cv2.VideoCapture('video6.mp4')
ret = True
frameCounter = 0
previousFrame = None
nextFrame = None
iterations = 0

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

代码语言:javascript
复制
backgroundImage = cv2.imread("image1.jpg")

4.逐帧分割视频

代码语言:javascript
复制
while (ret):
ret, frame = cap.read()

5.每隔两帧拍摄一次

代码语言:javascript
复制
if frameCounter % 2 == 1:
           nextFrame = frame        
if frameCounter % 2 == 0:
           frameCounter = 0
           previousFrame = frame       
frameCounter = frameCounter + 1
           iterations = iterations + 1

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

代码语言:javascript
复制
if iterations > 2:
  diff = cv2.absdiff(previousFrame, nextFrame)
  mask = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)

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

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

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

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

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

代码语言:javascript
复制
th = 3
isMask = mask > th
nonMask = mask <= th

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

代码语言:javascript
复制
result = np.zeros_like(nextFrame, np.uint8)

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

代码语言:javascript
复制
resized = cv2.resize(backgroundImage, (result.shape[1], result.shape[0]), interpolation = cv2.INTER_AREA)

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

代码语言:javascript
复制
result[isMask] = nextFrame[isMask]000000000000

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

代码语言:javascript
复制
result[nonMask] = resized[nonMask]

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

代码语言:javascript
复制
cv2.imwrite("output" + str(iterations) + ".jpg", result)

结果与结论

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

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

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

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

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

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

创建虚拟背景的其他方法

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小白学视觉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档