前言
闲来无事,偶然作乐,突发奇想,如何将跳舞视频进行抽象化:
1. 提取视频中人物的动作
2. 替换视频中背景图像
针对如上需求,在这里我将为大家带来制作骨架人物动作提取视频,大家可以分享给对象进行视频制作!
准备工作
在进行制作"抽象画面"制作的时候,我们需要做如下准备工作:
- 舞蹈视频(可以抖音等视频网站上面下载)
- 当然是本人中将要为大家带来的代码辣
制作步骤:
- 制作背景图像。这里我以纯色背景为例子,进行制作背景图像,大家也可以进行挑选自己喜欢的图像作为背景
- 人物动作提取。这里采用mediapipe库进行人物动作骨架提取
- 动作融合到背景图中。这里我们将人物动作提取出来,绘制到背景图像中去。
制作背景图像
创建图像:
在OpenCV中,黑白图像实际是一个二维数组,彩色图像是一个三维数组。在数组中每个元素就是图像对应位置的像素值。数组索引、像素行列、像素坐标关系如下:
a. 数组行索引 = 像素所在行数 - 1 = 像素纵坐标
b. 数组列索引 = 像素所在列数 - 1 = 像素横坐标
PS: 在黑白图像中,像素为0为纯黑色,像素为255为纯白色
创建随机像素三通道(RGB)图像:
- 像素点下标为0([:, :, 0])是①通道,代表蓝色\
- 像素点下标为0([:, :, 1])是②通道,代表绿色\
- 像素点下标为0([:, :, 2])是③通道,代表红色
OpenCV彩色图像默认为BGR格式,是三维数组,第三个索引表示三基色颜色分量
RGBImg.py如下,我们可以设置指定的RGB图,然后输入视频帧Size即可:
import numpy as np import cv2 as cv R = int(input("请输入R值:")) G = int(input("请输入G值:")) B = int(input("请输入B值:")) width = int(input("请输入图像宽度:")) height = int(input("请输入图像高度:")) img = np.zeros((height, width, 3), np.uint8) img_rgb = img.copy() img_rgb[:, :, :] = [B, G, R] cv.imwrite('./1111.jpg', img_rgb) cv.imshow("img_rgb", img_rgb) cv.waitKey() cv.destroyAllWindows() 复制代码
动作提取&融合
采用mediapipe库进行人体动作骨架的提取,其核心如下:
ML网络采用两步检测器和跟踪器,使用检测器,网络首先在一帧内定位人/姿势感兴趣区域(ROI)。跟踪器然后使用ROI裁剪帧作为输入,以预测ROI内的姿态地标和分割掩码。我们在对视频处理时,仅在需要时调用检测器,即:对于第一帧,并且当跟踪器无法再识别前一帧中存在的身体姿势时。对于其他帧,管道仅从前一帧的姿势标志导出ROI。管道被实现为一个MediaPipe图,该图使用来自pose landmarks模块的pose Lanemarks子图,并使用专用的pose renderer子图进行渲染。姿势地标子图在内部使用来自姿势检测模块的姿势检测子图。
程序逻辑:
- 初始化mediapipe模块
- 读取视频
- 设置mediapipe模块参数
- 设置静态写入
- 背景图像的读取
- 将提取骨骼框架绘制在背景图上
- 输出绘制好的图像
import cv2 import mediapipe as mp import numpy as np mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_pose = mp.solutions.pose cap = cv2.VideoCapture('test.mp4') with mp_pose.Pose( min_detection_confidence=0.7, min_tracking_confidence=0.7) as pose: name = 1 while cap.isOpened(): success, image = cap.read() if not success: print("Ignoring empty camera frame.") # If loading a video, use 'break' instead of 'continue'. break # To improve performance, optionally mark the image as not writeable to # pass by reference. image.flags.writeable = False image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = pose.process(image) # Draw the pose annotation on the image. image.flags.writeable = True # image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) image = cv2.imread('a.jpg') mp_drawing.draw_landmarks( image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS, landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style()) # Flip the image horizontally for a selfie-view display. cv2.imwrite('./111/%s.jpg' %name, cv2.flip(image, 1)) name = name + 1 # cv2.imshow('MediaPipe Pose', cv2.flip(image, 1)) # if cv2.waitKey(5) & 0xFF == 27: # break cap.release() 复制代码
成果展示
这里我选取的舞蹈片段,舞蹈名称:《傣》