前言
還記得上次通過 MediaPipe 估計人體姿態(tài)關(guān)鍵點(diǎn)驅(qū)動 3D 角色模型,雖然節(jié)省了動作 K 幀時間,但是網(wǎng)上還有一種似乎更方便的方法。MagicAnimate 就是其一,說是只要提供一張人物圖片和一段動作視頻 (舞蹈武術(shù)等),就可以完成圖片人物轉(zhuǎn)視頻。
于是我就去官網(wǎng)體驗了一下,發(fā)現(xiàn)動作的視頻長度不能超過 5 秒,當(dāng)然,如果說要整長視頻可以切多段處理再合成解決。主要的還是視頻需要那種背景相對較純的,不然提交表單一直報錯,還有他也不能處理畫面內(nèi)多人物的姿態(tài)估計。
多目標(biāo)人體姿態(tài)估計
為什么我要弄多目標(biāo),其實是我有次拿了一舞團(tuán)的視頻用 MediaPipe 檢測,發(fā)現(xiàn)一個畫面中只能采集到一個人的動作數(shù)據(jù)。雖然齊舞可能就一套動作,其他的角色模型可以復(fù)制粘貼,但是有些編舞為了好看,伴舞也會根據(jù)節(jié)奏作不同的變化。所以說對于我用來采集舞蹈數(shù)據(jù),這個很重要了,當(dāng)然他也可以用在多人互動的 AR 游戲,或用在同時培訓(xùn)多人的動作規(guī)范檢測等等場景。
要從單一人體檢測到多人體姿態(tài)估計,開始我是打算用 YOLO 對畫面中的多 Person 區(qū)塊讀出來,然后再將這些方塊遍歷交給 MediaPipe 對指定區(qū)域作人物動作節(jié)點(diǎn)識別。但是最后發(fā)現(xiàn)有現(xiàn)成的算法,就是 pytorch-openpose,所以果斷先用這個來體驗了一下。
pytorch-openpose 簡介
PyTorch-OpenPose 是一個基于 PyTorch 的開源庫,它實現(xiàn)了 OpenPose 的功能,可以進(jìn)行人的面部表情、軀干和四肢甚至手指的跟蹤。它不僅適用于單人也適用于多人,同時具有較好的魯棒性。要運(yùn)行 PyTorch-OpenPose,需要安裝支持 CUDA 的 PyTorch,以下例子有使用作者提供的預(yù)訓(xùn)練模型,通過拆分視頻幀,繪制多人物動作線條保存圖片,最后將圖片合成為視頻。
文章來源:http://www.zghlxwxcb.cn/news/detail-823812.html
環(huán)境
- scikit-image
- opencv-python
- scipy
- matplotlib
- numpy
文章來源地址http://www.zghlxwxcb.cn/news/detail-823812.html
編碼
幀拆分繪制
import cv2
import matplotlib.pyplot as plt
import copy
import numpy as np
import torch
from src import model
from src import util
from src.body import Body
from src.hand import Hand
body_estimation = Body('model/body_pose_model.pth')
hand_estimation = Hand('model/hand_pose_model.pth')
print(f"Torch device: {torch.cuda.get_device_name()}")
cap = cv2.VideoCapture("D:/3code/6pytorch/opencv_demo/12_open_pose/11.mp4")
cap.set(3, 640)
cap.set(4, 480)
indices = 1
while True:
ret, oriImg = cap.read()
if not ret:
break
candidate, subset = body_estimation(oriImg)
canvas = copy.deepcopy(oriImg)
canvas = util.draw_bodypose(canvas, candidate, subset)
# detect hand
hands_list = util.handDetect(candidate, subset, oriImg)
all_hand_peaks = []
for x, y, w, is_left in hands_list:
peaks = hand_estimation(oriImg[y:y+w, x:x+w, :])
peaks[:, 0] = np.where(peaks[:, 0]==0, peaks[:, 0], peaks[:, 0]+x)
peaks[:, 1] = np.where(peaks[:, 1]==0, peaks[:, 1], peaks[:, 1]+y)
all_hand_peaks.append(peaks)
canvas = util.draw_handpose(canvas, all_hand_peaks)
cv2.imwrite('image_out/img_{}.jpg'.format(indices), canvas)
indices += 1
print("images:", indices)
# cv2.imshow('demo', canvas)#一個窗口用以顯示原視頻
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
cap.release()
cv2.destroyAllWindows()
視頻合成
from pathlib import Path
import cv2
import os
# 將視頻video_path分割成圖片和音頻文件,保存到save_path文件夾中
def video2mp3_img(video_path, save_path, audio_path):
def video_split(video_path, save_path):
if not os.path.exists(save_path):
os.makedirs(save_path)
cap = cv2.VideoCapture(video_path)
i = 0
while True:
ret, frame = cap.read()
if ret:
cv2.imwrite(save_path + '/' + str(i) + '.jpg', frame)
i += 1
else:
break
cap.release()
if not os.path.exists(save_path):
os.makedirs(save_path)
# 視頻分割
video_split(video_path, save_path)
# 視頻轉(zhuǎn)音頻
# os.system("ffmpeg -i {} -vn -acodec copy {}/audio.mp3".format(video_path, audio_path))
os.system("ffmpeg -i {} -q:a 0 -map a {}/audio.mp3".format(video_path, audio_path))
# 音頻轉(zhuǎn)wav
# os.system("ffmpeg -i {}/audio.mp3 {}/audio.wav".format(save_path, save_path))
# 將video_imgout文件夾中的圖片合成視頻并且添加音頻文件video_img/audio.mp3
def img2mp4(image_out, save_name):
BASE_PATH = os.path.dirname(__file__)
# 讀取img size
img = cv2.imread("{}/img_1.jpg".format(image_out))
imgInfo = img.shape
size = (imgInfo[1], imgInfo[0])
files = []
for dirpath, dirnames, filenames in os.walk(image_out):
for filename in filenames:
fileName = Path(os.path.join(dirpath, filename))
files.append(os.path.join(dirpath, filename))
files = [file.replace('\\', '/') for file in files]
files.sort(key=lambda x: int(x.split('/')[-1].split('.')[0].split('_')[-1]))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
videoWrite = cv2.VideoWriter(f'videos/{save_name}.mp4', fourcc, 25, size) # 寫入對象 1 file name 3: 視頻幀率
for i in files:
img = cv2.imread(str(i))
videoWrite.write(img)
print(f'videos/{save_name}.mp4')
# 將video_img中的音頻文件添加到視頻中
# os.system("ffmpeg -i {}/videos/{}.mp4 -c:v copy -c:a aac -strict experimental {}/videos/{}.mp4".format(BASE_PATH, save_name, BASE_PATH, save_name))
if __name__ == '__main__':
BASE = os.path.dirname(__file__)
video_path = os.path.join(BASE, "videos/yangguo.mp4") # 視頻路徑
save_path = os.path.join(BASE, "video_img") # 拆解視頻保存路徑
audio_path = os.path.join(BASE, "audio") # 分離音頻保存路徑
# 視頻 ==> imgs
# video2mp3_img(video_path, save_path, audio_path)
# # imgs ==> 視頻
img2mp4("image_out", save_name='ldh')
到了這里,關(guān)于基于 pytorch-openpose 實現(xiàn) “多目標(biāo)” 人體姿態(tài)估計的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!