shengShenLan's picture
1
2d3633d
import cv2
import mediapipe as mp
import time
import matplotlib.pyplot as plt
import math
import numpy as np
import pandas as pd
from moviepy.video.io.bindings import mplfig_to_npimage
import os
plt.rcParams['font.sans-serif'] = ['SimHei']
# 导入姿态跟踪方法
mpPose = mp.solutions.pose # 姿态识别方法
pose = mpPose.Pose(static_image_mode=False, # 静态图模式,False代表置信度高时继续跟踪,True代表实时跟踪检测新的结果
#upper_body_only=False, # 是否只检测上半身
smooth_landmarks=True, # 平滑,一般为True
min_detection_confidence=0.5, # 检测置信度
min_tracking_confidence=0.5) # 跟踪置信度
# 检测置信度大于0.5代表检测到了,若此时跟踪置信度大于0.5就继续跟踪,小于就沿用上一次,避免一次又一次重复使用模型
# 导入绘图方法
mpDraw = mp.solutions.drawing_utils
# 定义一个处理视频的函数
def video_processor(video):
# 创建一个VideoCapture对象
cap = cv2.VideoCapture(video)
number_of_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
d = os.path.dirname(video)
# 创建一个VideoWriter对象,输出为mp4格式
for fourcc in cv2.VideoWriter_fourcc(*'ALL'):
print(f'{fourcc:04X}: {cv2.VideoWriter_fourccText(fourcc)}')
fourcc = cv2.VideoWriter_fourcc(*'avc1')
out = cv2.VideoWriter(os.path.join(d,'output.mp4'), fourcc, fps, (width, height))
print(os.path.exists(os.path.join(d,'output.mp4')))
# 创建一个图形对象
fig, ax = plt.subplots(figsize=(3, 3))
# ax.set_position((0.1, 0.1, 0.8, 0.4))
ax.set_xlim(0, number_of_frames)
ax.set_ylim(-10, 200)
ax.set_title('左腿夹角')
ax.set_xlabel('Time')
ax.set_ylabel('Angle')
line, = ax.plot([], [], 'r-')
# 定义更新曲线图的函数
def update_graph(frame, angle):
# 获取当前时间
time = frame
# 添加新的数据点
line.set_xdata(np.append(line.get_xdata(), time))
line.set_ydata(np.append(line.get_ydata(), angle))
# 返回更新后的曲线
return line
# 处理每一帧图像
# lmlist = [] # 存放人体关键点信息
left_23 = [] # 存 左髋关节的点
left_25 = [] # 存 左髋关节的点
a = [] # 存着所有角度
def angle(p1, p2):
x1, y1 = p1
x2, y2 = p2
dx = x2 - x1
dy = y2 - y1
return math.degrees(math.atan2(dy, dx))
frame_count = 0 # 记录帧数
while True:
# 读取一帧图像
success, img = cap.read()
if not success:
print('视频结束')
break
frame_count += 1
# 将图像转为RGB格式
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 将图像传给姿态识别模型
results = pose.process(imgRGB)
# 如果检测到体态就执行下面内容,没检测到就不执行
if results.pose_landmarks:
# 绘制姿态坐标点
mpDraw.draw_landmarks(img, results.pose_landmarks, mpPose.POSE_CONNECTIONS)
# 获取32个人体关键点坐标, index记录是第几个关键点
for index, lm in enumerate(results.pose_landmarks.landmark):
# 保存每帧图像的宽、高、通道数
h, w, c = img.shape
# 转换为像素坐标
cx, cy = int(lm.x * w), int(lm.y * h)
# 保存坐标信息
# lmlist.append((cx, cy))
if index == 23:
left_23.append([cx, cy])
if index == 25:
left_25.append([cx, cy])
# 在关键点上画圆圈
cv2.circle(img, (cx,cy), 3, (0,255,0), cv2.FILLED)
# 计算左腿夹角
if len(left_23) != 0 and len(left_25) != 0:
a.append(angle(left_23[-1],left_25[-1]))
# 更新曲线图
update_graph(frame_count, a[-1])
# 将图像转换为numpy数组
graph = mplfig_to_npimage(fig)
# 将曲线图叠加到视频上
img[-graph.shape[0]:,-graph.shape[1]:,:] = graph
# 写入新的视频文件
out.write(img)
# 释放资源
out.release()
cap.release()
# 返回输出视频的路径
print(video)
print(os.path.join(d,'output.mp4'))
print(os.path.exists(os.path.join(d,'output.mp4')))
return os.path.join(d,'output.mp4')
import gradio as gr
demo = gr.Interface(fn=video_processor, title='滑板招式姿态识别',
inputs=gr.Video(source="upload"), outputs=gr.Video()
# examples=["Ollie120.mp4"]
)
demo.launch()