最近,一位同事向提出了一个挑战——构建一个计算机视觉模型,能够在不扭曲视频中动态对象的情况下插入任何图像。这个项目非常有趣,在工作过程中也乐在其中。与静态图像不同,视频的动态特性使得处理起来异常困难。不能简单地识别和跟踪静态对象。复杂度提升了几个层次,这正是对图像处理和计算机视觉技术的掌握发挥作用的地方。
决定在视频背景中添加一个标志。稍后将详细阐述的挑战是如何插入一个标志,使其不会妨碍视频中任何给定动态对象的自然表现。使用Python和OpenCV构建了这个计算机视觉系统,并在本文中分享了方法。
本文将使用图像处理概念和OpenCV。有一系列全面的免费课程和文章,可以帮助快速上手这些主题:
这将是计算机视觉的一个非常不常见的用例。将在视频中嵌入一个标志。现在可能会想——这有什么大不了的?可以直接将标志贴在视频上,对吧?然而,这个标志可能会隐藏视频中的一些有趣动作。如果标志阻碍了前面的动态对象,那就没有多大意义了,也会让编辑看起来业余。
因此,必须弄清楚如何将标志添加到背景中的某个位置,使其不会阻挡视频中正在进行的主要动作。查看下面的视频——左半部分是原始视频,右半部分是标志出现在舞者背后的墙上:
从pexels.com这个提供免费库存视频的网站上获取了这个视频。正如之前提到的,目标是在视频中放置一个标志,使其应该出现在某个动态对象的后面。所以,目前将使用OpenCV的标志。可以使用任何想要的标志(也许是最喜欢的运动队?)。可以从下载视频和标志。
在实现这个项目之前,让先了解一下方法。为了执行这项任务,将借助图像遮罩。让给展示一些插图来理解这项技术。假设想在图像(图2)中放置一个矩形(图1),以便第二个图像中的圆形应该出现在矩形的上方:
所以,期望的结果应该像这样:
# 假设代码
然而,这并不那么简单。当从图1中取出矩形并将其插入图2时,它将出现在粉红色圆圈的上方:
# 假设代码
这不是想要的。圆圈应该在矩形的前面。那么,让了解如何解决这个问题。这些图像本质上是数组。这些数组的值是像素值,每种颜色都有自己的像素值。所以,会以某种方式将矩形的像素值设置为1,当它与图5中的圆圈重叠时,而保持矩形的其余像素值不变。
在图6中,由蓝色虚线包围的区域是将要放置矩形的区域。让用R来表示这个区域。将R的所有像素值都设置为1。然而,会保持整个粉红色圆圈的像素值不变:
下一步是将矩形的像素值与R的像素值相乘。由于任何数字乘以1都等于它本身,所以所有R中为1的像素值将被矩形的像素值替换。同样,矩形中为1的像素值将被图6的像素值替换。最终输出将是这样的:
# 假设代码
这就是将要使用的技术,将OpenCV标志嵌入到视频中跳舞的人后面。让开始吧!
可以使用Jupyter Notebook或任何选择的IDE,并按照以下步骤操作。首先导入必要的库。
# 导入库的代码
接下来,将指定包含标志和视频的工作目录的路径。请注意,应该在下面的代码片段中指定“路径”:
# 指定路径的代码
所以,已经加载了标志图像和视频的第一帧。现在让看看这些图像或数组的形状:
# 查看图像形状的代码
两个输出都是三维的。第一个维度是图像的高度,第二个维度是图像的宽度,第三个维度是图像的通道数,即蓝色、绿色和红色。
现在,让绘制并查看标志和视频的第一帧:
# 绘制图像的代码
为了创建图像遮罩,需要处理动态对象出现在放置标志的同一区域的问题。正如之前讨论的,需要使标志允许自己被动态对象遮挡。
目前,将放置标志的区域有广泛的像素值。理想情况下,这个区域的所有像素值应该是相同的。那么,如何做到这一点呢?将使用HSV(色调、饱和度、值)颜色空间的帮助:
图像在RGB颜色空间中。将把它转换成HSV图像。下面的图像是HSV版本:
# 转换颜色空间的代码
下一步是找到仅在绿色虚线框内部分的HSV值的范围。结果表明,框内的大多数像素值范围从[6, 10, 68]到[30, 36, 122]。这些分别是较低和较高的HSV范围。
现在,使用这个HSV值的范围,可以创建一个二进制遮罩。这个遮罩不过是像素值为0或255的图像。所以,落在HSV值的上下范围内的像素将等于255,其余像素将为0。
# 创建遮罩的代码
# 插入标志的代码