前言
事情的起因是最近在研究利用FFmpeg替换绿幕视频的背景,当然这个并不是本文要探讨的问题,主要是在这个过程中笔者在思考假设我现在拥有的素材背景不是纯色的,有没有什么方案可以将人抠出来呢?ps:类似的场景比较常见的应该是视频聊天时的背景替换吧。
于是就想到的机器学习,利用模型抠人像。通过GPT和百度等途径了解到Google的MediaPipe提供了一套人像分割的能力。所以本文主要记录的是笔者通过MediaPipe进行人像分割,再对每一帧进行背景替换,使用FFmpeg合成视频,最终生成一个绿幕视频这么一个过程。
MediaPipe
细节的东西就不介绍了,因为咱不熟悉,大家可以通过MediaPipe官网了解。
对于人像分割,MediaPipe也给出了开发引导,也可以通过MediaPipe Studio在线尝试效果。
Python实现
可以先PC上通过Python运行看看效果,通过询问GPT再稍作修改的python脚本是长这样的:
import cv2
import numpy as np
import mediapipe as mp
import os
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
input_path = "input.mp4"
output_video_path = "output.mp4"
base_options = python.BaseOptions(model_asset_path='selfie_segmenter.tflite')
options = vision.ImageSegmenterOptions(base_options=base_options,
running_mode=vision.RunningMode.VIDEO,
output_category_mask=True)
# 创建保存分割后帧的目录
os.makedirs("temp_frames", exist_ok=True)
os.makedirs("segmented_frames", exist_ok=True)
cap = cv2.VideoCapture(input_path)
# 获取视频的帧率和大小
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("fps: {}, width: {}, height: {}".format(fps, width, height))
frame_number = 0
segmenter = vision.ImageSegmenter.create_from_options(options)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 保存帧为临时图像文件
frame_path = f"temp_frames/temp_frame_{frame_number}.jpg"
# print("frame: {}".format(frame))
# 视频文件的当前位置,以ms为单位
ts = cap