前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >经典的计算机视觉项目–如何在视频中的对象后面添加图像

经典的计算机视觉项目–如何在视频中的对象后面添加图像

作者头像
代码医生工作室
发布2020-06-17 21:08:41
2.8K0
发布2020-06-17 21:08:41
举报
文章被收录于专栏:相约机器人相约机器人

总览

  • 在移动物体后面添加图像是经典的计算机视觉项目
  • 了解如何使用传统的计算机视觉技术在视频中添加logo

介绍

一位同事带来了一个挑战-建立一个计算机视觉模型,该模型可以在视频中插入任何图像而不会扭曲移动的对象。正如所想象的那样,这是一个非常有趣的项目,而对此进行了大量工作。

由于视频的动态特性,众所周知,处理视频非常困难。与图像不同,没有可以轻松识别和跟踪的静态对象。复杂性级别上升了几个级别–这就是对图像处理和计算机视觉技术的关注。

决定在背景中加上logo。将在稍后详细说明的挑战是,以不妨碍任何给定视频中对象的动态特性的方式插入logo。使用Python和OpenCV构建了此计算机视觉系统-并在本文中分享了方法。

在本文中,将使用图像处理概念和OpenCV。

目录

  1. 了解问题陈述
  2. 获取该项目的数据
  3. 为计算机视觉项目设定蓝图
  4. 在Python中实现该技术-添加logo!

了解问题陈述

这将是计算机视觉中非常罕见的用例。将在视频中嵌入logo。现在必须要思考–这有什么大不了的?可以简单地将logo粘贴到视频顶部,对吗?

但是,该logo可能只是在视频中隐藏了一些有趣的操作。如果logo妨碍前面的移动物体怎么办?这没有多大意义,并使编辑看起来很业余。

因此,必须弄清楚如何将logo添加到背景中的某个位置,以使其不会阻碍视频中正在进行的主要操作。观看下面的视频-左半部分是原始视频,右半部分上的logo出现在舞者后面的墙上:

这就是将在本文中实现的想法。

获取该项目的数据

我已从pexels.com(一个免费股票视频网站)上拍摄了此视频。正如我之前提到的,我们的目标是在视频中放置logo,使其应出现在某个移动物体的后面。因此,目前我们将使用OpenCV本身的logo。您可以使用任何想要的logo(也许是您最喜欢的运动队?)。

可以从此处下载视频和logo。

https://drive.google.com/file/d/1mXJtJOMTZYm-W6rQavdclbBUEuj3JL4v/view?usp=sharing

为计算机视觉项目设定蓝图

在实施此项目之前,让首先了解该方法。为了执行此任务,将使用图像遮罩。展示一些插图以了解该技术。

假设要在图像(图2)中放置一个矩形(图1),以使第二个图像中的圆应出现在矩形的顶部:

因此,所需的结果应如下所示:

但是,它并不是那么简单。当从图1中提取矩形并将其插入图2中时,它将出现在粉红色圆圈的顶部:

这不是想要的。圆应该在矩形的前面。因此了解如何解决此问题。

这些图像本质上是数组。这些数组的值是像素值,每种颜色都有自己的像素值。因此将以某种方式将应该与矩形重叠的矩形的像素值设置为1(在图5中),而将矩形的其余像素值保持不变。

在图6中,用蓝色虚线包围的区域是放置矩形的区域。用R表示该区域。还将R的所有像素值都设置为1。但是将整个粉红色圆圈的像素值保持不变:

下一步是将矩形的像素值与R的像素值相乘。由于将任何数字乘以1都会得到该数字本身,因此R的所有那些像素值1都将由矩形的像素替换。类似地,矩形的像素值为1将被图6的像素替换。最终的输出结果如下所示:

这是将用于在视频中跳舞的家伙后面嵌入OpenCVlogo的技术。开始做吧!

在Python中实现该技术-添加logo!

可以使用Jupyter Notebook或您选择的任何IDE,然后继续进行。将首先导入必要的库。

导入库

代码语言:javascript
复制
import cv2
import re
import os
import random
import numpy as np
import matplotlib.pyplot as plt
from os.path import isfile, join

注意:本教程使用的OpenCV库的版本是4.0.0。

加载图像

接下来,将指定保存logo和视频的工作目录的路径。请注意,应该在下面的代码段中指定“路径”:

代码语言:javascript
复制
# specify path to the working directory
path = ".../"
 
# read logo image
logo = cv2.imread(path+"opencv_logo.png")
 
# read the first frame of the video
cap = cv2.VideoCapture(path+"Pexels Videos 2675513.mp4")
ret, frame = cap.read()

因此,已加载logo图像和视频的第一帧。现在看一下这些图像或数组的形状:

代码语言:javascript
复制
logo.shape, frame.shape

输出:(((240,195,3),(1080,1920,3))

两个输出都是3维的。第一维是图像的高度,第二维是图像的宽度,而第三维是图像中通道的数量,即蓝色,绿色和红色。

现在,绘制并查看logo和视频的第一帧:

代码语言:javascript
复制
plt.imshow(logo)
plt.show()
代码语言:javascript
复制
plt.imshow(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
plt.show()

创建图像蒙版的技术

框架尺寸比logo大得多。因可以在许多地方放置logo。但是,将logo放置在框架的中央来说似乎很完美,因为大多数操作将围绕视频中的该区域进行。因此将logo放入框架中,如下所示:

不必担心logo中的黑色背景。稍后将在黑色区域中将像素值设置为1。现在要解决的问题是处理出现在放置logo的同一区域中的移动物体。

如前所述,需要使logo被移动的物体遮挡住。

现在将logo放入的区域具有广泛的像素值。理想情况下,该区域中的所有像素值都应相同。那么该怎么做呢?

必须使绿色虚线框包围的墙的像素具有相同的值。可以借助HSV(色相,饱和度,值)色彩空间来做到这一点:

图像在RGB色彩空间中。将其转换为HSV图片。下图是HSV版本:

下一步是仅找到绿色虚线框内零件的HSV值范围。事实证明,该框中的大多数像素的范围是[6、10、68]到[30、36、122]。这分别是HSV的下限和上限。

现在,使用此范围的HSV值,可以创建一个二进制掩码。此蒙版只不过是像素值为0或255的图像。因此,落入HSV值上下范围的像素将等于255,其余像素将为0。

下面给出的是根据HSV图像准备的蒙版。黄色区域中的所有像素的像素值为255,其余像素的像素值为0:

现在,可以根据需要轻松地将绿色虚线框中的像素值设置为1。回到代码:

代码语言:javascript
复制
# upper and lower range of HSV
lower = np.array([6,10,68])
upper = np.array([30,36,122])
 
# create kernel for image dilation
kernel = np.ones((3,3),np.uint8)
 
# execute the couple of lines below everytime you run the following while loop
cap = cv2.VideoCapture(path+"Pexels Videos 2675513.mp4")
cnt = 0
 
# loop to load, pre-process and display the frames
while(True):
    ret, f = cap.read()
     
    # extract the area where we will place the logo
    # the dimensions of this area should match with those of the logo
    mini_frame = f[500:740,875:1070,:]
     
    # create HSV image
    hsv = cv2.cvtColor(f, cv2.COLOR_BGR2HSV)
     
    # create binary mask
    mask = cv2.inRange(hsv, lower, upper)
     
    # perform dilation on the mask to reduce noise
    dil = cv2.dilate(mask,kernel,iterations = 5)
     
    # extract the area where we will place the logo
    # create 3 channels
    mini_dil = np.zeros_like(mini_frame)
    mini_dil[:,:,0] = dil[500:740,875:1070]
    mini_dil[:,:,1] = dil[500:740,875:1070]
    mini_dil[:,:,2] = dil[500:740,875:1070]
     
    # copy image of logo
    logo_copy = logo.copy()
     
    # set pixel values to 1 where the pixel values of the mask is 0
    logo_copy[mini_dil == 0] = 1
     
    # set pixel values to 1 where the pixel values of the logo is 0
    logo_copy[logo == 0] = 1
     
    # set pixel values to 1 where the pixel values of the logo is not 1
    mini_frame[logo_copy != 1] = 1
     
    # merge images (array multiplication)
    mini_frame = mini_frame*logo_copy
     
    # insert logo in the frame
    f[500:740,875:1070,:] = mini_frame
     
    # resize the frame (optional)
    f = cv2.resize(f, (480, 270), interpolation = cv2.INTER_AREA)
     
    # display frame
    cv2.imshow('frame', f)
     
    # save frame
    # cv2.imwrite(path+'frames/'+str(cnt)+'.png',f)
    cnt+= 1
     
    if cv2.waitKey(20) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

上面的代码段将加载视频中的帧,对其进行预处理,并创建HSV图像和蒙版,最后将logo插入视频中。

尾注

在本文中,介绍了一个非常有趣的计算机视觉用例,并从头开始实现了它。在此过程中,还学习了如何使用图像阵列以及如何从这些阵列创建遮罩。

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

本文分享自 相约机器人 微信公众号,前往查看

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

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

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