Python计算机视觉:在阈值化图像中使用center_of_mass()函数寻找每个物体的中心坐标

本文介绍使用Python进行计算机视觉处理,通过形态学操作处理阈值化图像,并利用center_of_mass()函数找到图像中每个物体的中心坐标,最终在图像中标绘出这些中心点。

Python计算机视觉:在阈值化图像中使用center_of_mass()函数寻找每个物体的中心坐标

《Python计算机视觉》第一章练习第七题:
使用形态学操作处理阈值化图像。在发现一些参数能够产生好的结果后,使用center_of_mass()函数寻找每个物体的中心坐标,将其在图像中绘制出来。
以下是我的尝试:

from PIL import Image
from numpy import *
from pylab import *
from scipy.ndimage import measurements,morphology,label

im=array(Image.open('test4.jpg').convert('L'))
im=1*(im<128)

#载入图像,然后使用阈值化操作,以保证处理的图像为二值图像
im_open=morphology.binary_opening(im,ones((5,5)),iterations=2)

labels_open,nbr_objects_open=measurements.label(im_open)

#求出每个物体中心点坐标						
a=measurements.center_of_mass(im_open,labels_open,[i+1 for i in range(nbr_objects_open)])

figure()
gray()
imshow(im_open)

#在图像中把中心点绘制出来
plot([p[1] for p in a],[p[0] for p in a],'r*')

show()

原图像
这是代码中用到的‘test4.jpg’图像

如图
如图,红星点即为所求中心点。

import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy import signal, interpolate from scipy.spatial.distance import euclidean from scipy.signal import find_peaks, savgol_filter # 假设数据加载函数 - 需要根据实际数据格式调整 def load_motion_data(file_path): """ 加载运动数据 返回: DataFrame,包含帧号和33个关键点的坐标 """ # 这里需要根据实际数据格式实现 # 假设数据格式为: frame, x1, y1, x2, y2, ... x33, y33 data = pd.read_csv(file_path) return data # 计算质心函数 def calculate_center_of_mass(data, weights=None): """ 计算每一帧的质心坐标 weights: 各关键点的权重,如果不提供则使用均匀权重 """ if weights is None: weights = np.ones(33) / 33 # 均匀权重 x_cols = [f'x{i}' for i in range(1, 34)] y_cols = [f'y{i}' for i in range(1, 34)] com_x = np.average(data[x_cols], weights=weights, axis=1) com_y = np.average(data[y_cols], weights=weights, axis=1) return com_x, com_y # 计算垂直速度函数 def calculate_vertical_velocity(y, fps=30): """ 计算垂直速度 fps: 视频帧率 """ # 使用中心差分法计算速度 dy = np.gradient(y, 1/fps) return dy # 确定起跳和落地时刻 def detect_takeoff_landing(ankle_y, fps=30, threshold=0.1): """ 通过脚踝关键点的垂直速度确定起跳和落地时刻 ankle_y: 脚踝关键点的y坐标序列 fps: 视频帧率 threshold: 速度阈值 """ # 计算垂直速度 v_y = calculate_vertical_velocity(ankle_y, fps) # 平滑速度曲线 v_y_smooth = savgol_filter(v_y, 11, 3) # 寻找起跳时刻 (速度由负转正) takeoff_frame = None for i in range(1, len(v_y_smooth)): if v_y_smooth[i-1] <= threshold and v_y_smooth[i] > threshold: takeoff_frame = i break # 寻找落地时刻 (速度由正急剧变负) landing_frame = None if takeoff_frame: for i in range(takeoff_frame + 1, len(v_y_smooth)): if v_y_smooth[i-1] > -threshold and v_y_smooth[i] < -threshold: landing_frame = i break return takeoff_frame, landing_frame, v_y_smooth # 计算身体角度 def calculate_body_angles(data, frame): """ 计算特定帧的身体角度 """ # 获取关键点坐标 # 假设关键点索引按照标准人体姿态估计模型 (如OpenPose) # 这里需要根据实际关键点索引调整 # 躯干前倾角: 髋部中点与颈部关键点的连线与垂直方向的夹角 mid_hip_x = (data.loc[frame, 'x8'] + data.loc[frame, 'x11']) / 2 mid_hip_y = (data.loc[frame, 'y8'] + data.loc[frame, 'y11']) / 2 neck_x = data.loc[frame, 'x1'] neck_y = data.loc[frame, 'y1'] # 计算向量 vec_x = neck_x - mid_hip_x vec_y = neck_y - mid_hip_y # 注意坐标系方向 # 计算与垂直方向的夹角 trunk_angle = np.degrees(np.arctan2(vec_x, vec_y)) # 类似方法可以计算其他角度 # 大腿与躯干夹角、小腿与大腿夹角等 return trunk_angle # 主分析函数 def analyze_jump_process(data_file): """ 分析跳远过程的主函数 """ # 加载数据 data = load_motion_data(data_file) # 计算质心 com_x, com_y = calculate_center_of_mass(data) # 获取脚踝关键点 (假设索引为7和10) left_ankle_y = data['y7'] right_ankle_y = data['y10'] ankle_y = (left_ankle_y + right_ankle_y) / 2 # 使用双脚平均值 # 确定起跳和落地时刻 takeoff_frame, landing_frame, v_y = detect_takeoff_landing(ankle_y) # 滞空阶段分析 if takeoff_frame and landing_frame: print(f"起跳时刻: 第{takeoff_frame}帧") print(f"落地时刻: 第{landing_frame}帧") print(f"滞空时间: {(landing_frame - takeoff_frame) / 30:.2f}秒") # 假设30fps # 分析滞空阶段身体姿态变化 flight_frames = range(takeoff_frame, landing_frame + 1) trunk_angles = [calculate_body_angles(data, f) for f in flight_frames] # 绘制结果 plt.figure(figsize=(12, 8)) plt.subplot(2, 2, 1) plt.plot(com_x, com_y) plt.plot(com_x[takeoff_frame], com_y[takeoff_frame], 'go', label='Takeoff') plt.plot(com_x[landing_frame], com_y[landing_frame], 'ro', label='Landing') plt.xlabel('X Position') plt.ylabel('Y Position') plt.title('Center of Mass Trajectory') plt.legend() plt.subplot(2, 2, 2) plt.plot(v_y) plt.axvline(x=takeoff_frame, color='g', linestyle='--', label='Takeoff') plt.axvline(x=landing_frame, color='r', linestyle='--', label='Landing') plt.xlabel('Frame') plt.ylabel('Vertical Velocity') plt.title('Vertical Velocity of Ankles') plt.legend() plt.subplot(2, 2, 3) plt.plot(flight_frames, trunk_angles) plt.xlabel('Frame') plt.ylabel('Trunk Angle (degrees)') plt.title('Trunk Angle During Flight') plt.subplot(2, 2, 4) # 可以添加其他分析,如膝关节角度等 plt.tight_layout() plt.show() return takeoff_frame, landing_frame, flight_frames, trunk_angles else: print("未能检测到起跳或落地时刻") return None, None, None, None
最新发布
09-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值