訂閱
糾錯(cuò)
加入自媒體

一文教你使用OpenCV+CVzone進(jìn)行實(shí)時(shí)背景替換

介紹OpenCV是一個(gè)開源計(jì)算機(jī)視覺庫(kù),可提供播放不同圖像和視頻流的權(quán)限,還有助于端到端項(xiàng)目,如對(duì)象檢測(cè)、人臉檢測(cè)、對(duì)象跟蹤等。CVzone是一個(gè)計(jì)算機(jī)視覺包,可以讓我們輕松運(yùn)行像人臉檢測(cè)、手部跟蹤、姿勢(shì)估計(jì)等,以及圖像處理和其他 AI 功能。它的核心是使用 OpenCV 和 MediaPipe 庫(kù)。

為什么需要實(shí)時(shí)背景去除?

由于許多原因,視頻的背景需要修改,如背景中有很多其他中斷或背景顏色不適合該人。因此,我們使用實(shí)時(shí)背景替換技術(shù)來替換背景并添加替換為所需內(nèi)容。

流行的背景去除技術(shù)

圖像剪切路徑 - 如果圖像的主題具有銳利的邊緣,則使用此技術(shù)。所有落在路徑之外的元素都將被消除。

圖像剪切 – 在這里,我們剪切幀中所需的區(qū)域或主題并刪除背景。

圖像遮罩 – 如果圖像有褶邊或細(xì)邊緣,我們可以使用圖像遮罩技術(shù)。

擦除背景 – 使用任何不同的工具擦除圖像的背景許多著名的應(yīng)用程序使用背景去除技術(shù)并用自定義技術(shù)替換它。在這里,我們將實(shí)現(xiàn)類似的東西,使用 OpenCV 和 CVzone。

讓我們開始實(shí)施

安裝所需的模塊。

-- pip install OpenCV-python
-- pip install cvzone
-- pip install mediapipe
首先,讓我們檢查一下我們的網(wǎng)絡(luò)攝像頭是否工作正常。import cv2
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
while True:
success, img = cap.read()
cv2.imshow("Image", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
如果你有網(wǎng)絡(luò)攝像頭,上面的代碼會(huì)彈出一個(gè)窗口,這里的幀大小是 640 X 480。所以我們需要注意,因?yàn)楸尘疤鎿Q圖像的大小應(yīng)該與幀大小相同,即 640 X 480 .

現(xiàn)在在這里創(chuàng)建項(xiàng)目目錄中的文件夾,我正在創(chuàng)建一個(gè)名為*'BackgroundImages'*的文件夾。你可以下載任何圖像或任意數(shù)量的圖像并將它們放在此目錄中。項(xiàng)目結(jié)構(gòu)將如下圖所示:

讓我們?cè)趩为?dú)的 python 文件中編寫一小段代碼,將*“BackgroundImages”*文件夾中的所有圖像大小調(diào)整 為 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, (640, 480))
           cv2.imwrite('D:/pycharmprojects/BackgroundRemover/BackgroundImages/'+f, img)
           print(*["Image", f, "is resized to 640 X 480"])
上面的代碼將讀取指定文件夾中的圖像(jpg)文件,并一次將所有圖像調(diào)整為 640 X480。調(diào)整所有圖像大小后的輸出

現(xiàn)在我們都準(zhǔn)備好實(shí)現(xiàn)背景替換技術(shù)了。導(dǎo)入需要的模塊import cv2
import cvzone
from cvzone.SelfiSegmentationModule import SelfiSegmentation
import os
在上面的模塊中,*“SelfSegmentation”*用于刪除框架的背景并將其替換為我們目錄中的圖像。cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
# 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.a(chǎn)ppend(img)
indexImg = 0
在上面的代碼中,我們采取從網(wǎng)絡(luò)攝像頭輸入,并且還設(shè)置幀寬度為640 X 480然后調(diào)用SelfiSegmentation() ,并將其分配給一個(gè)變量segmentor,并且為了在顯示幀每秒(fps)的輸出幀,我們使用*cvzone.FPS()*函數(shù)。然后我們創(chuàng)建一個(gè)存在于BackgroundImages文件夾中的圖像列表,我們遍歷該列表并讀取每個(gè)圖像并將其附加到一個(gè)空列表中。初始索引設(shè)置為零。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           indexImg +=1
   elif key == ord('q'):
       break
現(xiàn)在主要部分在 while 循環(huán)中從網(wǎng)絡(luò)攝像頭讀取幀,我們使用*segmentor.removeBG()*函數(shù)從幀中刪除背景并將其替換為目錄中的圖像。在上面的代碼中,你可以看到我們已經(jīng)向segmentor.removeBG()函數(shù)傳遞了三個(gè)參數(shù) ,即來自網(wǎng)絡(luò)攝像頭的圖像幀(img),然后是目錄中存在的圖像列表以及圖像索引(imgList[indexImg) ]),最后是閾值。如果閾值設(shè)置為 1,則閾值會(huì)削減所有內(nèi)容,這里我們將其設(shè)置為 0.8,為了獲得更好的邊緣,請(qǐng)使用不同的閾值。然后我們使用cvzone.stackImages堆疊圖像*,* 這里我們將獲得背景替換圖像或幀的輸出。然后使用一個(gè)簡(jiǎn)單的 if 語(yǔ)句,分配鍵來更改背景。例如,如果我們有 10 張背景圖像,根據(jù)上面的代碼,我們可以使用鍵“a”或鍵“d”來更改幀的背景。整個(gè)代碼如下。import cv2
import cvzone
from cvzone.SelfiSegmentationModule import SelfiSegmentation
import os
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
# 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.a(chǎn)ppend(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           indexImg +=1
   elif key == ord('q'):
       break
輸出截圖如下輸出 1:

輸出 2:

聲明: 本文由入駐維科號(hào)的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無(wú)評(píng)論

暫無(wú)評(píng)論

    人工智能 獵頭職位 更多
    掃碼關(guān)注公眾號(hào)
    OFweek人工智能網(wǎng)
    獲取更多精彩內(nèi)容
    文章糾錯(cuò)
    x
    *文字標(biāo)題:
    *糾錯(cuò)內(nèi)容:
    聯(lián)系郵箱:
    *驗(yàn) 證 碼:

    粵公網(wǎng)安備 44030502002758號(hào)