2025-08-14 18:24:45 +08:00
|
|
|
|
import cv2
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
from ultralytics import YOLO
|
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_angle_between_lines(line1_start, line1_end, line2_start, line2_end):
|
|
|
|
|
|
"""
|
|
|
|
|
|
计算两条线之间的夹角(单位:度),范围 0~180°
|
|
|
|
|
|
"""
|
|
|
|
|
|
v1 = np.array(line1_end) - np.array(line1_start)
|
|
|
|
|
|
v2 = np.array(line2_end) - np.array(line2_start)
|
|
|
|
|
|
|
|
|
|
|
|
if np.linalg.norm(v1) == 0 or np.linalg.norm(v2) == 0:
|
|
|
|
|
|
return 0.0
|
|
|
|
|
|
|
|
|
|
|
|
v1_u = v1 / np.linalg.norm(v1)
|
|
|
|
|
|
v2_u = v2 / np.linalg.norm(v2)
|
|
|
|
|
|
|
|
|
|
|
|
dot = np.clip(np.dot(v1_u, v2_u), -1.0, 1.0)
|
|
|
|
|
|
angle_rad = np.arccos(dot)
|
|
|
|
|
|
angle_deg = np.degrees(angle_rad)
|
|
|
|
|
|
|
|
|
|
|
|
return angle_deg
|
|
|
|
|
|
|
|
|
|
|
|
def draw_keypoints_and_angle(image, keypoints, angle):
|
|
|
|
|
|
"""
|
|
|
|
|
|
绘制关键点、连线和角度文本
|
|
|
|
|
|
"""
|
|
|
|
|
|
pts = [(int(kp[0]), int(kp[1])) for kp in keypoints]
|
|
|
|
|
|
|
|
|
|
|
|
# 绘制关键点
|
|
|
|
|
|
for i, pt in enumerate(pts):
|
|
|
|
|
|
color = (0, 0, 255) if i in [0, 2] else (255, 0, 0) # 1,3 红;2,4 蓝
|
|
|
|
|
|
cv2.circle(image, pt, radius=8, color=color, thickness=-1)
|
|
|
|
|
|
cv2.putText(image, f'{i+1}', (pt[0]+10, pt[1]-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)
|
|
|
|
|
|
|
|
|
|
|
|
# 连线
|
|
|
|
|
|
cv2.line(image, pts[0], pts[2], color=(0, 255, 0), thickness=3) # 1-3 绿
|
|
|
|
|
|
cv2.line(image, pts[1], pts[3], color=(255, 255, 0), thickness=3) # 2-4 黄
|
|
|
|
|
|
|
|
|
|
|
|
# 显示角度
|
|
|
|
|
|
text = f"Angle: {angle:.1f}°"
|
|
|
|
|
|
cv2.putText(image, text, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 255), 3)
|
|
|
|
|
|
|
|
|
|
|
|
return image
|
|
|
|
|
|
|
|
|
|
|
|
# ====================== 用户配置 ======================
|
|
|
|
|
|
MODEL_PATH = '/home/hx/yolo/ultralytics_yolo11-main/runs/train/exp_pose/weights/best.pt' # 替换为你的模型路径
|
2025-09-01 14:14:18 +08:00
|
|
|
|
IMAGE_PATH = '/home/hx/yolo/output_masks/1.jpg' # 替换为你的测试图像路径
|
2025-08-14 18:24:45 +08:00
|
|
|
|
CONF_THRESHOLD = 0.25
|
|
|
|
|
|
SAVE_RESULT = True
|
|
|
|
|
|
SAVE_PATH = '/home/hx/yolo/test_image/result_with_angle.jpg'
|
|
|
|
|
|
SHOW_IMAGE = True
|
|
|
|
|
|
|
|
|
|
|
|
# ====================== 主程序(带时间统计)======================
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
# 1. 加载模型(加载时间也计入首次推理)
|
|
|
|
|
|
print("正在加载模型...")
|
|
|
|
|
|
model = YOLO(MODEL_PATH)
|
|
|
|
|
|
print(f"✅ 模型加载完成: {MODEL_PATH}")
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 读取图像
|
|
|
|
|
|
img = cv2.imread(IMAGE_PATH)
|
|
|
|
|
|
if img is None:
|
|
|
|
|
|
raise FileNotFoundError(f"无法加载图像: {IMAGE_PATH}")
|
|
|
|
|
|
|
|
|
|
|
|
print(f"正在处理图像: {IMAGE_PATH}")
|
|
|
|
|
|
|
|
|
|
|
|
# --- 开始计时:总耗时 ---
|
|
|
|
|
|
total_start = time.time()
|
|
|
|
|
|
|
|
|
|
|
|
# --- 模型推理计时 ---
|
|
|
|
|
|
infer_start = time.time()
|
|
|
|
|
|
results = model(img, conf=CONF_THRESHOLD, device='0') # 可指定 GPU
|
|
|
|
|
|
infer_end = time.time()
|
|
|
|
|
|
inference_time = (infer_end - infer_start) * 1000 # 转为毫秒
|
|
|
|
|
|
|
|
|
|
|
|
# --- 后处理计时 ---
|
|
|
|
|
|
post_start = time.time()
|
|
|
|
|
|
|
|
|
|
|
|
detection_count = 0
|
|
|
|
|
|
for result in results:
|
|
|
|
|
|
if result.keypoints is not None:
|
|
|
|
|
|
kpts = result.keypoints.cpu().numpy() # (N, 4, 3)
|
|
|
|
|
|
for i in range(len(kpts)):
|
|
|
|
|
|
instance_kpts = kpts[i]
|
|
|
|
|
|
|
|
|
|
|
|
pt1 = instance_kpts[0][:2]
|
|
|
|
|
|
pt2 = instance_kpts[1][:2]
|
|
|
|
|
|
pt3 = instance_kpts[2][:2]
|
|
|
|
|
|
pt4 = instance_kpts[3][:2]
|
|
|
|
|
|
|
|
|
|
|
|
angle = calculate_angle_between_lines(pt1, pt3, pt2, pt4)
|
|
|
|
|
|
img = draw_keypoints_and_angle(img, instance_kpts, angle)
|
|
|
|
|
|
detection_count += 1
|
|
|
|
|
|
print(f"✅ 检测到实例 {i+1},角度 = {angle:.1f}°")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("未检测到关键点")
|
|
|
|
|
|
|
|
|
|
|
|
post_end = time.time()
|
|
|
|
|
|
post_time = (post_end - post_start) * 1000
|
|
|
|
|
|
total_end = time.time()
|
|
|
|
|
|
total_time = (total_end - total_start) * 1000
|
|
|
|
|
|
|
|
|
|
|
|
# --- 输出时间统计 ---
|
|
|
|
|
|
print("\n" + "="*50)
|
|
|
|
|
|
print(" 推理时间统计")
|
|
|
|
|
|
print("="*50)
|
|
|
|
|
|
print(f"模型推理耗时: {inference_time:6.2f} ms")
|
|
|
|
|
|
print(f"后处理耗时: {post_time:6.2f} ms")
|
|
|
|
|
|
print(f"总耗时: {total_time:6.2f} ms")
|
|
|
|
|
|
print(f"FPS ≈ {1000 / total_time:6.2f}")
|
|
|
|
|
|
print(f"检测目标数: {detection_count}")
|
|
|
|
|
|
print("="*50)
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 保存或显示
|
|
|
|
|
|
if SAVE_RESULT:
|
|
|
|
|
|
cv2.imwrite(SAVE_PATH, img)
|
|
|
|
|
|
print(f"结果图像已保存至: {SAVE_PATH}")
|
|
|
|
|
|
|
|
|
|
|
|
if SHOW_IMAGE:
|
|
|
|
|
|
cv2.imshow("Keypoint Detection with Angle", img)
|
|
|
|
|
|
print("按任意键关闭窗口...")
|
|
|
|
|
|
cv2.waitKey(0)
|
|
|
|
|
|
cv2.destroyAllWindows()
|