使用 OpenCV+CVzone 进行实时背景替换

点击下方AI算法与图像处理”,一起进步!

重磅干货,第一时间送达

介绍
OpenCV是一个开源计算机视觉库,可提供播放不同图像和视频流的权限,还有助于端到端项目,如对象检测、人脸检测、对象跟踪等。
CVzone是一个计算机视觉包,可以让我们轻松运行像人脸检测、手部跟踪、姿势估计等,以及图像处理和其他 AI 功能。它的核心是使用 OpenCV 和 MediaPipe 库。请点击此处获取更多信息。
  • https://github.com/cvzone/cvzone

为什么需要实时背景去除?

由于许多原因,视频的背景需要修改,如背景中有很多其他中断或背景颜色不适合该人。因此,我们使用实时背景替换技术来替换背景并添加替换为所需内容。

流行的背景去除技术

图像剪切路径 - 如果图像的主题具有锐利的边缘,则使用此技术。所有落在路径之外的元素都将被消除。
图像剪切 – 在这里,我们剪切帧中所需的区域或主题并删除背景。
图像遮罩 – 如果图像有褶边或细边缘,我们可以使用图像遮罩技术。
擦除背景 – 使用任何不同的工具擦除图像的背景
许多著名的应用程序使用背景去除技术并用自定义技术替换它。在这里,我们将实现类似的东西,使用 OpenCV 和 CVzone。

让我们开始实施

安装所需的模块。

   
   
   
-- pip install OpenCV-python

-- pip install cvzone

-- pip install mediapipe
首先,让我们检查一下我们的网络摄像头是否工作正常。

   
   
   
import cv2

cap = cv2.VideoCapture(0)
cap.set(3640)
cap.set(4480)

while True:
success, img = cap.read()
cv2.imshow("Image", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
如果你有网络摄像头,上面的代码会弹出一个窗口,这里的帧大小是 640 X 480。所以我们需要注意,因为背景替换图像的大小应该与帧大小相同,即 640 X 480 .
现在在这里创建项目目录中的文件夹,我正在创建一个名为*'BackgroundImages'*的文件夹。你可以下载任何图像或任意数量的图像并将它们放在此目录中。
项目结构将如下图所示:
让我们在单独的 python 文件中编写一小段代码,将*“BackgroundImages”*文件夹中的所有图像大小调整 为 640 X 480。

   
   
   
import cv2
import os

for root, subdirs, files in os.walk('D:/pycharmprojects/BackgroundRemover/BackgroundImages'):
    for f in files:
        if f.endswith('jpg'):
            # print(f)
            img = cv2.imread('D:/pycharmprojects/BackgroundRemover/BackgroundImages/' + f)
            img = cv2.resize(img, (640480))
            cv2.imwrite('D:/pycharmprojects/BackgroundRemover/BackgroundImages/'+f, img)
            print(*["Image", f, "is resized to 640 X 480"])

上面的代码将读取指定文件夹中的图像(jpg)文件,并一次将所有图像调整为 640 X480。
调整所有图像大小后的输出
现在我们都准备好实现背景替换技术了。
导入需要的模块

   
   
   
import cv2
import cvzone
from cvzone.SelfiSegmentationModule import SelfiSegmentation
import os
在上面的模块中,*“SelfSegmentation”*用于删除框架的背景并将其替换为我们目录中的图像。

   
   
   
cap = cv2.VideoCapture(0)
cap.set(3640)
cap.set(4480)
# cap.set(cv2.CAP_PROP_FPS, 60)
segmentor = SelfiSegmentation()
fpsReader = cvzone.FPS()

   
   
   
# imgBG = cv2.imread("BackgroundImages/3.jpg")

listImg = os.listdir("BackgroundImages")
imgList = []
for imgPath in listImg:
    img = cv2.imread(f'BackgroundImages/{imgPath}')
    imgList.append(img)

indexImg = 0
在上面的代码中,我们采取从网络摄像头输入,并且还设置帧宽度为640 X 480
然后调用SelfiSegmentation() ,并将其分配给一个变量segmentor,并且为了在显示帧每秒(fps)的输出帧,我们使用*cvzone.FPS()*函数。
然后我们创建一个存在于BackgroundImages文件夹中的图像列表,我们遍历该列表并读取每个图像并将其附加到一个空列表中。初始索引设置为零。

   
   
   
while True:
    success, img = cap.read()
    # imgOut = segmentor.removeBG(img, (255,0,255), threshold=0.83)
    imgOut = segmentor.removeBG(img, imgList[indexImg], threshold=0.8)

    imgStack = cvzone.stackImages([img, imgOut], 2,1)
    _, imgStack = fpsReader.update(imgStack)
    print(indexImg)
    cv2.imshow("image", imgStack)
    key = cv2.waitKey(1)
    if key == ord('a'):
        if indexImg>0:
            indexImg -=1
    elif key == ord('d'):
        if indexImg<len(imgList)-1:
            indexImg +=1
    elif key == ord('q'):
        break
现在主要部分在 while 循环中从网络摄像头读取帧,我们使用*segmentor.removeBG()*函数从帧中删除背景并将其替换为目录中的图像。
在上面的代码中,你可以看到我们已经向segmentor.removeBG()函数传递了三个参数 ,即来自网络摄像头的图像帧(img),然后是目录中存在的图像列表以及图像索引(imgList[indexImg) ]),最后是阈值。如果阈值设置为 1,则阈值会削减所有内容,这里我们将其设置为 0.8,为了获得更好的边缘,请使用不同的阈值。
然后我们使用cvzone.stackImages堆叠图像*,* 这里我们将获得背景替换图像或帧的输出。然后使用一个简单的 if 语句,分配键来更改背景。
例如,如果我们有 10 张背景图像,根据上面的代码,我们可以使用键“a”或键“d”来更改帧的背景。
整个代码如下。

   
   
   
import cv2
import cvzone
from cvzone.SelfiSegmentationModule import SelfiSegmentation
import os

cap = cv2.VideoCapture(0)
cap.set(3640)
cap.set(4480)
# cap.set(cv2.CAP_PROP_FPS, 60)

segmentor = SelfiSegmentation()
fpsReader = cvzone.FPS()

# imgBG = cv2.imread("BackgroundImages/3.jpg")

listImg = os.listdir("BackgroundImages")
imgList = []
for imgPath in listImg:
    img = cv2.imread(f'BackgroundImages/{imgPath}')
    imgList.append(img)

indexImg = 0

while True:
    success, img = cap.read()
    # imgOut = segmentor.removeBG(img, (255,0,255), threshold=0.83)
    imgOut = segmentor.removeBG(img, imgList[indexImg], threshold=0.8)

    imgStack = cvzone.stackImages([img, imgOut], 2,1)
    _, imgStack = fpsReader.update(imgStack)
    print(indexImg)
    cv2.imshow("image", imgStack)
    key = cv2.waitKey(1)
    if key == ord('a'):
        if indexImg>0:
            indexImg -=1
    elif key == ord('d'):
        if indexImg<len(imgList)-1:
            indexImg +=1
    elif key == ord('q'):
        break


输出截图如下
输出 1:
输出 2:
整个代码也可以在这里找到:
https://github.com/BakingBrains/Real-Time_Background_remover
参考:
https://www.youtube.com/watch?v=k7cVPGpnels

☆ END ☆
如果看到这里,说明你喜欢这篇文章,请 转发、点赞
努力分享优质的计算机视觉相关内容,欢迎关注:
     
              
              
              
个人微信(如果没有备注不拉群!
请注明: 地区+学校/企业+研究方向+暱称



下载1:何恺明顶会分享


AI算法与图像处理」公众号后台回复:何恺明,即可下载。总共有6份PDF,涉及 ResNet、Mask RCNN等经典工作的总结分析


下载2:终身受益的编程指南:Google编程风格指南


AI算法与图像处理」公众号后台回复:c++,即可下载。历经十年考验,最权威的编程规范!



   
            
            
            
下载3 CVPR2021

AI算法与图像处公众号后台回复: CVPR 即可下载1467篇CVPR 2020论文 和 CVPR 2021 最新论文



本文分享自微信公众号 - AI算法与图像处理(AI_study)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章