使用OpenCV進行簡單的人像分割與合成

圖像合成

實現思路

經過背景建模的方法,對源圖像中的動態人物前景進行分割,再將目標圖像做爲背景,進行合成操做,得到一個可用的合成影像。python

實現步驟以下。算法

使用BackgroundSubtractorMOG2進行背景分割

BackgroundSubtractorMOG2是一個以高斯混合模型爲基礎的背景前景分割算法,數組

混合高斯模型

分佈機率是K個高斯分佈的和,每一個高斯分佈有屬於本身的 \(\mu\)\(\sigma\) 參數,以及對應的權重參數,權重值必須爲正數,全部權重的和必須等於1,以確保公式給出數值是合理的機率密度值。換句話說若是咱們把該公式對應的輸入空間合併起來,結果將等於1。app

回到原算法,它的一個特色是它爲每個像素選擇一個合適數目的高斯分佈。基於高斯模型的指望和標準差來判斷混合高斯模型模型中的哪一個高斯模型更有可能對應這個像素點,若是不符合就會被斷定爲前景。ide

使用人像識別填充面部信息

建立級聯分類器

face_cascade = cv2.CascadeClassifier()
face_cascade.load(
    '/usr/local/anaconda3/envs/OpenCV/lib/python3.8/site-packages/cv2/data/haarcascade_frontalface_default.xml')

使用OpenCV自帶的級聯分類器,加載OpenCV的基礎人像識別數據。測試

識別源圖像中的人像

faces = face_cascade.detectMultiScale(gray, 1.3, 5)

使用形態學填充分割出來的前景

# 形態學開運算去噪點
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
for i in range(15):
    fgmask = cv2.dilate(fgmask, kernel, iterations=1)

經過開操做去掉前景圖像數組中的噪點,而後重複進行膨脹,填充前景輪廓。spa

將人像與目標背景進行合成

def resolve(o_img, mask, faces):
    if len(faces) == 0:
        return
    (x, y, w, h) = faces[0]
    rgb_mask_front = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
    rgb_mask_front = cv2.bitwise_not(rgb_mask_front)
    cv2.circle(rgb_mask_front, (int(x + w / 2), int(y + h / 2)), int((w + h) / 4), (0, 0, 0), thickness=-1)
    o_img = cv2.subtract(o_img, rgb_mask_front)
    return o_img

將分割出來的部分取反再與源圖像進行減操做,至關於用一個Mask從原圖中摳出一部分。code

再與背景進行加操做orm

out = resolve(frame, fgmask, faces)
out = cv2.add(out, c_frame)

代碼實現

import numpy as np
import cv2
import os

# 經典的測試視頻
camera = cv2.VideoCapture('./source/background_test2.avi')
cap = cv2.VideoCapture('./source/camera_test2.avi')
face_cascade = cv2.CascadeClassifier()
face_cascade.load(
     os.getcwd()+'/source/haarcascade_frontalface_default.xml')
# 形態學操做須要使用
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
# 建立混合高斯模型用於背景建模
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=False)


def resolve(o_img, mask, faces):
    if len(faces) == 0:
        return
    (x, y, w, h) = faces[0]
    rgb_mask_front = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
    rgb_mask_front = cv2.bitwise_not(rgb_mask_front)
    cv2.circle(rgb_mask_front, (int(x + w / 2), int(y + h / 2)), int((w + h) / 4), (0, 0, 0), thickness=-1)
    o_img = cv2.subtract(o_img, rgb_mask_front)
    return o_img


while True:
    ret, frame = cap.read()
    c_ret, c_frame = camera.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    fgmask = fgbg.apply(frame)
    # 形態學開運算去噪點
    fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
    gray_camera = cv2.cvtColor(c_frame, cv2.COLOR_BGR2GRAY)

    for i in range(15):
        fgmask = cv2.dilate(fgmask, kernel, iterations=1)

    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    out = resolve(frame, fgmask, faces)
    out = cv2.add(out, c_frame)
    cv2.imshow('Result', out)
    cv2.imshow('Mask', fgmask)
    k = cv2.waitKey(150) & 0xff
    if k == 27:
        break
out.release()
camera.release()
cap.release()
cv2.destroyAllWindows()
相關文章
相關標籤/搜索