我是Tina表姐,毕业于中国人民大学,对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在,我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合,专为本次赛题设计,旨在帮助您深入理解数学建模的每一个环节。
本次2025年高教杯全国大学生数学建模国赛C题可以做如下考虑 (部分公式和代码因为知乎排版问题显示不完整,文中代码仅有部分,完整论文格式标准,包含全部代码)

在这里插入图片描述
可视化:
在这里插入图片描述

在这里插入图片描述
问题 1

附件 1 是两位立定跳远运动者的跳远视频、位置信息和跳远成绩。其中,位置信息包含运动者在整个跳远过程中的 33 个关键节点(见附件 2)在视频不同帧的位置坐标。请确定运动者在跳远过程中的起跳和落地时刻,并描述滞空阶段(从起跳到落地)的运动过程。

这个问题要求:

  1. 确定起跳时刻
  2. 确定落地时刻
  3. 描述滞空阶段的运动过程

需要基于AI人体姿态估计技术获得的33个关键节点在不同视频帧中的位置坐标数据来分析运动者的立定跳远动作。

问题1:立定跳远起跳和落地时刻确定及滞空阶段分析

1. 数学模型建立

1.1 问题分析

立定跳远运动可分为三个阶段:

  • 准备阶段:运动者蹲下准备
  • 滞空阶段:从起跳到落地
  • 落地阶段:双脚接触地面

关键是识别起跳时刻和落地时刻,并分析滞空阶段的运动特征。

1.2 关键节点选择

基于人体关键节点,重点关注:

  • 脚部节点:左脚踝(15)、右脚踝(16)、左脚尖(19)、右脚尖(20)
  • 重心节点:髋部中心、胸部中心
  • 手部节点:左手腕(9)、右手腕(10)

1.3 数学模型

1.3.1 起跳时刻确定模型

模型1:脚部离地检测法

设第t帧时,左脚踝坐标为(x₁ᵗ, y₁ᵗ),右脚踝坐标为(x₂ᵗ, y₂ᵗ)
定义脚部高度函数:
h_foot(t) = min(y₁ᵗ, y₂ᵗ)

起跳时刻判定条件:
t_takeoff = min{t | h_foot(t) - h_foot(t-1) > δ₁ 且 Δh_foot(t) > δ₂}

其中:
- δ₁:脚部高度变化阈值
- δ₂:连续上升高度阈值
- Δh_foot(t) = h_foot(t+k) - h_foot(t-k),k为时间窗口

模型2:垂直速度突变检测法

计算重心垂直速度:
v_y(t) = [y_center(t+1) - y_center(t-1)] / (2Δt)

其中y_center(t) = [y_hip(t) + y_chest(t)] / 2

起跳时刻判定:
t_takeoff = argmax{|v_y(t+1) - v_y(t)| | t ∈ [t_start, t_end]}
1.3.2 落地时刻确定模型

模型1:脚部触地检测法

落地时刻判定条件:
t_landing = min{t > t_takeoff | h_foot(t) ≤ h_ground + ε 且 v_y(t) < 0}

其中:
- h_ground:地面高度基准
- ε:触地容差

模型2:垂直速度零点检测法

t_landing = min{t > t_takeoff | v_y(t) ≤ 0 且 v_y(t-1) > 0}
1.3.3 滞空阶段运动分析模型

重心轨迹模型

重心坐标:
x_center(t) = [x_hip(t) + x_chest(t)] / 2
y_center(t) = [y_hip(t) + y_chest(t)] / 2

抛物线拟合:
y = ax² + bx + c

参数估计:
[a, b, c]ᵀ = (XᵀX)⁻
基于AI人体姿态估计技术的立定跳远运动分析,我将为问题1建立数学模型来确定起跳和落地时刻,并描述滞空阶段的运动过程。

问题1:起跳和落地时刻确定及滞空阶段运动过程分析

1.1 数学模型建立

设运动者在第ttt帧的人体关键节点位置为Pi(t)=(xi(t),yi(t))P_i(t) = (x_i(t), y_i(t))Pi(t)=(xi(t),yi(t)),其中i=1,2,...,33i = 1, 2, ..., 33i=1,2,...,33表示33个关键节点。

重心计算模型:
G⃗(t)=1N∑i=1Nwi⋅Pi(t)\vec{G}(t) = \frac{1}{N} \sum_{i=1}^{N} w_i \cdot P_i(t)G (t)=N1i=1NwiPi(t)

其中wiw_iwi为第iii个关键点的权重系数,N=33N=33N=33为关键点总数。

垂直速度计算模型:
vy(t)=Gy(t+1)−Gy(t−1)2Δtv_y(t) = \frac{G_y(t+1) - G_y(t-1)}{2\Delta t}vy(t)=tGy(t+1)Gy(t1)

其中Δt\Delta tΔt为帧间时间间隔,Gy(t)G_y(t)Gy(t)为重心的垂直坐标。

垂直加速度计算模型:
ay(t)=vy(t+1)−vy(t−1)2Δta_y(t) = \frac{v_y(t+1) - v_y(t-1)}{2\Delta t}ay(t)=tvy(t+1)vy(t1)

1.2 起跳时刻判定准则

主要判定指标:

  1. 足部离地判定:

    • 设左右脚关键点为Pankle_leftP_{ankle\_left}Pankle_leftPankle_rightP_{ankle\_right}Pankle_right
    • 起跳判定条件:min⁡(yankle_left(t),yankle_right(t))>yground+ϵ\min(y_{ankle\_left}(t), y_{ankle\_right}(t)) > y_{ground} + \epsilonmin(yankle_left(t),yankle_right(t))>yground+ϵ
  2. 重心垂直速度判定:
    vy(t)>vthreshold 且 dvydt>0v_{y}(t) > v_{threshold} \text{ 且 } \frac{dv_y}{dt} > 0vy(t)>vthreshold  dtdvy>0

  3. 综合起跳时刻:
    ttakeoff=arg⁡min⁡t{vy(t)>0.1 且足部离地}t_{takeoff} = \arg\min_t \{v_y(t) > 0.1 \text{ 且足部离地}\}ttakeoff=argtmin{vy(t)>0.1 且足部离地}

1.3 落地时刻判定准则

落地判定指标:

  1. 足部触地判定:
    ∣yankle_left(t)−yground∣<ϵ 或 ∣yankle_right(t)−yground∣<ϵ|y_{ankle\_left}(t) - y_{ground}| < \epsilon \text{ 或 } |y_{ankle\_right}(t) - y_{ground}| < \epsilonyankle_left(t)yground<ϵ  yankle_right(t)yground<ϵ

  2. 重心垂直速度变化:
    vy(t)<0 且 ∣ay(t)∣>aimpact_thresholdv_y(t) < 0 \text{ 且 } |a_y(t)| > a_{impact\_threshold}vy(t)<0  ay(t)>aimpact_threshold

  3. 综合落地时刻:
    tlanding=arg⁡min⁡t{t>ttakeoff 且足部触地 且 vy(t)<0}t_{landing} = \arg\min_t \{t > t_{takeoff} \text{ 且足部触地 且 } v_y(t) < 0\}tlanding=argtmin{t>ttakeoff 且足部触地  vy(t)<0}

1.4 滞空阶段运动过程描述

滞空时间计算:
Tflight=tlanding−ttakeoffT_{flight} = t_{landing} - t_{takeoff}Tflight=tlandingttakeoff

重心运动轨迹方程:

在滞空阶段,重心遵循抛物线运动:
{x(t)=x0+vx0⋅(t−ttakeoff)y(t)=y0+vy0⋅(t−ttakeoff)−12g(t−ttakeoff)2\begin{cases} x(t) = x_0 + v_{x0} \cdot (t - t_{takeoff}) \\ y(t) = y_0 + v_{y0} \cdot (t - t_{takeoff}) - \frac{1}{2}g(t - t_{takeoff})^2 \end{cases}{x(t)=x0+vx0(tttakeoff)y(t)=y0+vy0(tttakeoff)21g(tttakeoff)2

其中:

  • x0,y0x_0, y_0x0,y0为起跳时重
    我来为问题1提供一个完整的Python代码解决方案,用于分析立定跳远运动者的起跳、落地时刻和滞空阶段运动过程。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.signal import find_peaks, savgol_filter
import cv2
from sklearn.preprocessing import StandardScaler
from scipy.optimize import curve_fit

class StandingLongJumpAnalyzer:
    def __init__(self):
        # 根据人体关键节点定义重要关节点索引
        self.key_points = {
            'head': [0, 1, 2, 3, 4],  # 头部关键点
            'shoulders': [5, 6],       # 肩膀
            'elbows': [7, 8],          # 肘部
            'wrists': [9, 10],         # 手腕
            'hips': [11, 12],          # 髋部
            'knees': [13, 14],         # 膝盖
            'ankles': [15, 16],        # 脚踝
            'feet': [17, 18, 19, 20, 21, 22, 23, 24]  # 脚部
        }
        
    def load_data(self, file_path):
        """加载运动者位置数据"""
        try:
            data = pd.read_csv(file_path)
            return data
        except:
            # 如果是其他格式,需要相应调整
            return None
    
    def calculate_center_of_mass(self, positions):
        """计算质心位置"""
        # 使用主要身体部位计算质心
        main_points = (self.key_points['shoulders'] + 
                      self.key_points['hips'] + 
                      self.key_points['knees'])
        
        com_x = np.mean([positions[:, point*2] for point in main_points], axis=0)
        com_y = np.mean([positions[:, point*2+1] for point in main_points], axis=0)
        
        return com_x, com_y
    
    def detect_takeoff_landing(self, positions, frame_rate=30):
        """检测起跳和落地时刻"""
        # 计算脚部平均高度
        feet_indices = [point*2+1 for point in self.key_points['feet']]
        feet_y = np.mean([positions[:, idx] for idx in feet_indices], axis=0)
        
        # 平滑处理
        feet_y_smooth = savgol_filter(feet_y, window_length=5, polyorder=2)
        
        # 计算垂直速度
        vertical_velocity = np.gradient(feet_y_smooth)
        
        # 计算垂直加速度
        vertical_acceleration = np.gradient(vertical_velocity)
        
        # 检测起跳时刻:脚部开始快速上升
        takeoff_candidates = find_peaks(vertical_velocity, height=np.std(vertical_velocity))[0]
        if len(takeoff_candidates) == 0:
            takeoff_frame = np.argmax(vertical_velocity)
        else:
            takeoff_frame = takeoff_candidates[0]
        
        # 检测落地时刻:脚部高度开始稳定在较低位置
        # 寻找起跳后的最低点
        landing_start = takeoff_frame + 10  # 至少在起跳后10帧
        if landing_start < len(feet_y_smooth):
            landing_candidates = find_peaks(-feet_y_smooth[landing_start:], 
                                          height=-np.percentile(feet_y_smooth, 25))[0]
            if len(landing_candidates) > 0:
                landing_frame = landing_start + landing_candidates[0]
            else:
                landing_frame = np.argmin(feet_y_smooth[landing_start:])
        else:
            landing_frame = np.argmin(feet_y_smooth[landing_start:])

        # 计算起跳高度
        takeoff_height = feet_y_smooth[takeoff_frame]

        # 计算腾空时间
        flight_time = landing_frame - takeoff_frame

        # 计算最大高度
        max_height = np.max(feet_y_smooth[takeoff_frame:landing_frame])

        # 计算起跳速度
        takeoff_velocity = vertical_velocity[takeoff_frame]

        # 计算落地速度
        landing_velocity = vertical_velocity[landing_frame]
        return takeoff_frame, landing_frame, takeoff_height, flight_time, max_height, takeoff_velocity, landing_velocity

# 使用函数计算每个视频的起跳和落地信息
jump_data = []
for video_path in video_paths:
    video = cv2.VideoCapture(video_path)
    frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = video.get(cv2.CAP_PROP_FPS)
    video.release()

更多内容具体可以看看我的下方名片!
里面包含有本次竞赛一手资料与分析!
另外在赛中,我们也会陪大家一起解析建模比赛
记得关注Tina表姐哦~

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐