使用 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源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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