commit c134abf7499ced86fb6d768489b8638e98894c9f Author: 琉璃月光 <15630071+llyg777@user.noreply.gitee.com> Date: Tue Oct 21 11:07:29 2025 +0800 first commit diff --git a/ailai_pc/1.py b/ailai_pc/1.py new file mode 100644 index 0000000..212789d --- /dev/null +++ b/ailai_pc/1.py @@ -0,0 +1,25 @@ +from ultralytics import YOLO +import cv2 +import torch + +# 加载模型 +model = YOLO('best.pt') + +# 读取一张真实图像 +img_path = '/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/point2/train/1.jpg' # 替换成您的图像路径 +image = cv2.imread(img_path) + +# 将图像转换成RGB格式,并调整大小 +image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) +image_resized = cv2.resize(image_rgb, (640, 640)) + +# 进行推理 +results = model(image_resized) + +# 打印关键点数据形状和样本 +if len(results) > 0 and hasattr(results[0], 'keypoints') and results[0].keypoints is not None: + print("Keypoints data shape:", results[0].keypoints.data.shape) + if results[0].keypoints.data.shape[0] > 0: + print("Keypoints data sample:", results[0].keypoints.data[0, :12]) +else: + print("No keypoints detected or invalid keypoints data.") \ No newline at end of file diff --git a/ailai_pc/1.xml b/ailai_pc/1.xml new file mode 100644 index 0000000..f53ff4e --- /dev/null +++ b/ailai_pc/1.xml @@ -0,0 +1,42 @@ + + train + 1.jpg + /home/hx/桌面/ailai_test/train/1.jpg + + Unknown + + + 1280 + 720 + 3 + + 0 + + robndbox + ban + Unspecified + 0 + 0 + + 630.9352 + 227.4174 + 538.9691 + 244.294 + 3.071593 + + + + robndbox + bag + Unspecified + 0 + 0 + + 655.631 + 218.0273 + 282.1343 + 179.1767 + 3.101593 + + + \ No newline at end of file diff --git a/ailai_pc/angle.py b/ailai_pc/angle.py new file mode 100644 index 0000000..398af50 --- /dev/null +++ b/ailai_pc/angle.py @@ -0,0 +1,145 @@ +from ultralytics import YOLO +import cv2 +import os +import numpy as np + +# 设置类别名称(必须与训练时一致) +CLASS_NAMES = ['ban', 'bag'] # ✅ 确保顺序正确,对应模型的 class_id +COLORS = [(0, 255, 0), (255, 0, 0)] # ban: 绿色, bag: 蓝色 + + +def get_best_angles_per_class(image_path, weight_path, return_degree=False): + """ + 输入: + image_path: 图像路径 + weight_path: YOLO OBB 权重路径 + return_degree: 是否返回角度(单位:度),否则为弧度 + 输出: + 字典:{ class_name: best_angle 或 None } + """ + img = cv2.imread(image_path) + if img is None: + print(f"❌ 无法读取图像:{image_path}") + return {cls: None for cls in CLASS_NAMES} + + model = YOLO(weight_path) + results = model(img, save=False, imgsz=640, conf=0.15, task='obb') + result = results[0] + + boxes = result.obb + if boxes is None or len(boxes) == 0: + print("⚠️ 未检测到任何目标。") + return {cls: None for cls in CLASS_NAMES} + + # 提取数据 + xywhr = boxes.xywhr.cpu().numpy() # (N, 5) -> cx, cy, w, h, r (弧度) + confs = boxes.conf.cpu().numpy() # (N,) + class_ids = boxes.cls.cpu().numpy().astype(int) # (N,) + + # 初始化结果字典 + best_angles = {cls: None for cls in CLASS_NAMES} + + # 对每个类别找置信度最高的框 + for class_id, class_name in enumerate(CLASS_NAMES): + mask = (class_ids == class_id) + if not np.any(mask): + print(f"🟡 未检测到类别: {class_name}") + continue + + # 找该类别中置信度最高的 + idx_in_class = np.argmax(confs[mask]) + global_idx = np.where(mask)[0][idx_in_class] + angle_rad = xywhr[global_idx][4] + + best_angles[class_name] = np.degrees(angle_rad) if return_degree else angle_rad + + return best_angles + + +def save_obb_visual(image_path, weight_path, save_path): + """ + 输入: + image_path: 图像路径 + weight_path: YOLO权重路径 + save_path: 保存带标注图像路径 + 功能: + 检测所有 OBB,绘制框、类别名、旋转角度,保存图片 + """ + img = cv2.imread(image_path) + if img is None: + print(f"❌ 无法读取图像:{image_path}") + return + + model = YOLO(weight_path) + results = model(img, save=False, imgsz=640, conf=0.05, task='obb') + result = results[0] + + boxes = result.obb + if boxes is None or len(boxes) == 0: + print("⚠️ 未检测到任何目标。") + # 仍保存原图 + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, img) + return + + # 提取信息 + xywhr = boxes.xywhr.cpu().numpy() + confs = boxes.conf.cpu().numpy() + class_ids = boxes.cls.cpu().numpy().astype(int) + + # 绘制 + annotated_img = img.copy() + for i in range(len(boxes)): + cx, cy, w, h, r = xywhr[i] + angle_deg = np.degrees(r) + class_id = class_ids[i] + class_name = CLASS_NAMES[class_id] if class_id < len(CLASS_NAMES) else f"cls{class_id}" + conf = confs[i] + color = COLORS[class_id % len(COLORS)] if class_id < len(CLASS_NAMES) else (128, 128, 128) + + # 绘制旋转框 + rect = ((cx, cy), (w, h), angle_deg) + box_pts = cv2.boxPoints(rect).astype(int) + cv2.polylines(annotated_img, [box_pts], isClosed=True, color=color, thickness=2) + + # 标注文本:类别 + 置信度 + 角度 + text = f"{class_name} {conf:.2f} {angle_deg:.1f}°" + font_scale = 0.7 + thickness = 2 + text_size, _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, font_scale, thickness) + + # 文本背景 + cv2.rectangle(annotated_img, + (box_pts[0][0], box_pts[0][1] - text_size[1] - 8), + (box_pts[0][0] + text_size[0], box_pts[0][1] + 2), + color, -1) + # 文本 + cv2.putText(annotated_img, text, + (box_pts[0][0], box_pts[0][1] - 5), + cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255, 255, 255), thickness) + + # 保存 + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, annotated_img) + print(f"✅ 检测结果已保存至: {save_path}") + + +# =============================== +# 示例调用 +# =============================== +if __name__ == "__main__": + weight = r"/home/hx/yolo/ultralytics_yolo11-main/runs/train/exp_obb3/weights/best.pt" + image = r"/home/hx/yolo/output_masks/2.jpg" + save_path = "./inference_results/visualized_2.jpg" + + # 获取每个类别的最佳角度(以度为单位) + angles_deg = get_best_angles_per_class(image, weight, return_degree=True) + print("\n🎯 各类别最佳旋转角度(度):") + for cls_name, angle in angles_deg.items(): + if angle is not None: + print(f" {cls_name}: {angle:.2f}°") + else: + print(f" {cls_name}: 未检测到") + + # 可视化所有检测结果 + save_obb_visual(image, weight, save_path) \ No newline at end of file diff --git a/ailai_pc/angle_and_diff.py b/ailai_pc/angle_and_diff.py new file mode 100644 index 0000000..1393eee --- /dev/null +++ b/ailai_pc/angle_and_diff.py @@ -0,0 +1,210 @@ +from ultralytics import YOLO +import cv2 +import numpy as np +import os + +# ================================ +# 配置区(所有固定参数放在这里) +# ================================ + +# --- 模型与类别 --- +CLASS_NAMES = ['ban', 'bag'] # 类别名称 +WEIGHT_PATH = r"/home/hx/yolo/ultralytics_yolo11-main/runs/train/exp_obb_ailai2/weights/best.pt" +IMAGE_PATH = r"/home/hx/ailai_image_obb/ailai_obb/camera01/1.jpg" + +# --- 结果保存路径 --- +RESULT_DIR = "./inference_results" +os.makedirs(RESULT_DIR, exist_ok=True) # 确保目录存在 +RESULT_IMAGE_PATH = os.path.join(RESULT_DIR, os.path.basename(IMAGE_PATH)) # 保存路径 +FIXED_BAG_CENTER_FILE = os.path.join(RESULT_DIR, "bag_center.txt") # 固定参考点,只读' + +# --- ban 的实际物理尺寸(单位:毫米 mm)--- +BAN_REAL_WIDTH_MM = 890 # 实际宽度(例如:800 mm) +BAN_REAL_HEIGHT_MM = 1990 # 实际高度(例如:1990 mm) + +# --- ban 在图像中的平均像素尺寸(由模型检测得到,稳定值)--- +BAN_PIXEL_WIDTH_PX = 536.35 # 图像中检测到的平均宽度(像素) +BAN_PIXEL_HEIGHT_PX = 242.83 # 图像中检测到的平均高度(像素) + +# --- 计算缩放因子(mm/px)--- +SCALE_X = BAN_REAL_WIDTH_MM / BAN_PIXEL_WIDTH_PX # mm/px +SCALE_Y = BAN_REAL_HEIGHT_MM / BAN_PIXEL_HEIGHT_PX # mm/px + +print(f"标定信息 1 像素 = {SCALE_X:.3f} mm (水平) {SCALE_Y:.3f} mm (垂直)") + +# --- 固定 bag 角度(单位:度)--- +FIXED_BAG_ANGLE_DEG = 0.0 # 固定参考角度 + +# ================================ +# 工具函数 +# ================================ + +def pixels_to_physical(dx_px, dy_px): + """ + 将像素偏移量转换为物理偏移量(毫米) + """ + dx_mm = dx_px * SCALE_X + dy_mm = dy_px * SCALE_Y + return dx_mm, dy_mm + +def load_center_from_txt(txt_path): + """加载文本中的中心点 (cx, cy)""" + if not os.path.exists(txt_path): + print(f"文件不存在 {txt_path}") + return None + try: + with open(txt_path, "r") as f: + line = f.readline().strip() + if not line: + return None + x, y = map(float, line.split()) + return (x, y) + except Exception as e: + print(f"读取文件失败 {txt_path} {e}") + return None + +def get_angles_and_centers(image_path, weight_path): + """获取每个类别的角度和中心点""" + img = cv2.imread(image_path) + if img is None: + print(f"无法读取图像 {image_path}") + return {cls: None for cls in CLASS_NAMES}, None + + model = YOLO(weight_path) + results = model(img, imgsz=640, conf=0.15, task='obb') + result = results[0] + + boxes = result.obb + if boxes is None or len(boxes) == 0: + print("未检测到任何目标") + return {cls: None for cls in CLASS_NAMES}, img + + xywhr = boxes.xywhr.cpu().numpy() + confs = boxes.conf.cpu().numpy() + class_ids = boxes.cls.cpu().numpy().astype(int) + + angles_and_centers = {} + for class_id, class_name in enumerate(CLASS_NAMES): + mask = (class_ids == class_id) + if not np.any(mask): + print(f"未检测到类别 {class_name}") + angles_and_centers[class_name] = None + continue + + idx_in_class = np.argmax(confs[mask]) + global_idx = np.where(mask)[0][idx_in_class] + cx, cy, w, h, r = xywhr[global_idx] + angle_deg = np.degrees(r) + + angles_and_centers[class_name] = { + 'angle': angle_deg, + 'center': (float(cx), float(cy)), + 'width': float(w), + 'height': float(h), + 'box_points': cv2.boxPoints(((cx, cy), (w, h), angle_deg)) # 获取四个角点 + } + + return angles_and_centers, img + +def draw_results_and_save(image, angles_and_centers, fixed_bag_center, save_path): + """绘制旋转框、中心点、标签、偏移向量,并保存图像""" + vis_img = image.copy() + + # 颜色定义 + colors = { + 'ban': (0, 255, 0), # 绿色 + 'bag': (255, 0, 0) # 蓝色 + } + + # 绘制每个检测结果 + for cls_name, info in angles_and_centers.items(): + if info is None: + continue + + # 绘制旋转框 + box_pts = np.int32(info['box_points']) + cv2.drawContours(vis_img, [box_pts], 0, colors[cls_name], 2) + + # 绘制中心点 + cx, cy = int(info['center'][0]), int(info['center'][1]) + cv2.circle(vis_img, (cx, cy), 5, (0, 0, 255), -1) # 红色实心圆 + + # 添加标签 + label = f"{cls_name} {info['angle']:.1f}°" + cv2.putText(vis_img, label, (cx - 30, cy - 10), + cv2.FONT_HERSHEY_SIMPLEX, 0.6, colors[cls_name], 2) + + # 绘制 fixed_bag_center 和偏移向量 + current_bag = angles_and_centers.get('bag') + if fixed_bag_center and current_bag: + fx, fy = int(fixed_bag_center[0]), int(fixed_bag_center[1]) + cx, cy = int(current_bag['center'][0]), int(current_bag['center'][1]) + + # 绘制 fixed center(空心圆) + cv2.circle(vis_img, (fx, fy), 7, (255, 255, 0), 2) # 青色 + + # 绘制从 fixed 到 current 的箭头(偏移向量) + cv2.arrowedLine(vis_img, (fx, fy), (cx, cy), (0, 255, 255), 2, tipLength=0.05) + + # 添加偏移文字 + dx_px = cx - fx + dy_px = cy - fy + dx_mm, dy_mm = pixels_to_physical(dx_px, dy_px) + offset_text = f"Δx={dx_mm:.1f}mm Δy={dy_mm:.1f}mm" + cv2.putText(vis_img, offset_text, (fx + 10, fy + 20), + cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 255), 2) + + # 保存图像 + cv2.imwrite(save_path, vis_img) + print(f"\n✅ 可视化结果已保存至: {save_path}") + +# =============================== +# 主程序 +# =============================== +if __name__ == "__main__": + # 1. 获取当前检测结果和图像 + angles_and_centers, img = get_angles_and_centers(IMAGE_PATH, WEIGHT_PATH) + if img is None: + exit(1) + + print("\n各类别旋转角度 中心点") + for cls_name, info in angles_and_centers.items(): + if info is not None: + print(f" {cls_name} 角度 {info['angle']:.2f} 中心点 {info['center'][0]:.2f} {info['center'][1]:.2f} 尺寸 {info['width']:.2f} {info['height']:.2f} px") + else: + print(f" {cls_name} 未检测到") + + # 2. 获取固定参考 bag 中心点 + fixed_bag_center = load_center_from_txt(FIXED_BAG_CENTER_FILE) + print(f"\n固定参考 bag 中心点 {fixed_bag_center}") + + # 3. 计算偏移量(像素) + current_bag = angles_and_centers.get('bag') + if current_bag and current_bag['center'] and fixed_bag_center: + dx_px = current_bag['center'][0] - fixed_bag_center[0] + dy_px = current_bag['center'][1] - fixed_bag_center[1] + + print(f"\n像素偏移量") + print(f" Δx {dx_px:.2f} px Δy {dy_px:.2f} px") + + # 转换为物理偏移量 + dx_mm, dy_mm = pixels_to_physical(dx_px, dy_px) + print(f"\n物理偏移量 基于 ban 尺寸标定") + print(f" ΔX {dx_mm:.2f} mm ΔY {dy_mm:.2f} mm") + + # 计算角度偏移量 + current_bag_angle = current_bag['angle'] + angle_diff = current_bag_angle - FIXED_BAG_ANGLE_DEG + print(f"\n角度偏移量") + print(f" 当前 bag 角度 {current_bag_angle:.2f}") + print(f" 固定 bag 角度 {FIXED_BAG_ANGLE_DEG}") + print(f" 角度差 {angle_diff:.2f}") + else: + print(f"\n偏移量计算失败 数据缺失") + if not current_bag: + print(" 未检测到 bag") + if not fixed_bag_center: + print(" 固定参考点文件为空或不存在") + + # 4. 绘制并保存可视化结果 + draw_results_and_save(img, angles_and_centers, fixed_bag_center, RESULT_IMAGE_PATH) \ No newline at end of file diff --git a/ailai_pc/annotations.xml b/ailai_pc/annotations.xml new file mode 100644 index 0000000..b4f1e64 --- /dev/null +++ b/ailai_pc/annotations.xml @@ -0,0 +1,3466 @@ + + + 1.1 + + + 197 + 10.17ailai + 576 + annotation + 0 + + 2025-10-19 08:02:10.197347+00:00 + 2025-10-20 07:34:00.089890+00:00 + default + 0 + 575 + + + + 140 + 0 + 575 + http://www.xj-robot.com:9000/api/jobs/140 + + + + huangxin + 2193534909@qq.com + + + + + + + + + + 2025-10-20 08:32:33.431770+00:00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ailai_pc/bag_bushu.py b/ailai_pc/bag_bushu.py new file mode 100644 index 0000000..a57228d --- /dev/null +++ b/ailai_pc/bag_bushu.py @@ -0,0 +1,171 @@ +import cv2 +import numpy as np +import math +from shapely.geometry import Polygon +from rknnlite.api import RKNNLite +import os + +CLASSES = ['clamp'] +nmsThresh = 0.4 +objectThresh = 0.5 + +# ------------------- 工具函数 ------------------- +def letterbox_resize(image, size, bg_color=114): + target_width, target_height = size + image_height, image_width, _ = image.shape + scale = min(target_width / image_width, target_height / image_height) + new_width, new_height = int(image_width * scale), int(image_height * scale) + image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA) + canvas = np.ones((target_height, target_width, 3), dtype=np.uint8) * bg_color + offset_x, offset_y = (target_width - new_width) // 2, (target_height - new_height) // 2 + canvas[offset_y:offset_y + new_height, offset_x:offset_x + new_width] = image + return canvas, scale, offset_x, offset_y + +class DetectBox: + def __init__(self, classId, score, xmin, ymin, xmax, ymax, angle): + self.classId = classId + self.score = score + self.xmin = xmin + self.ymin = ymin + self.xmax = xmax + self.ymax = ymax + self.angle = angle + +def rotate_rectangle(x1, y1, x2, y2, a): + cx, cy = (x1 + x2) / 2, (y1 + y2) / 2 + x1_new = int((x1 - cx) * math.cos(a) - (y1 - cy) * math.sin(a) + cx) + y1_new = int((x1 - cx) * math.sin(a) + (y1 - cy) * math.cos(a) + cy) + x2_new = int((x2 - cx) * math.cos(a) - (y2 - cy) * math.sin(a) + cx) + y2_new = int((x2 - cx) * math.sin(a) + (y2 - cy) * math.cos(a) + cy) + x3_new = int((x1 - cx) * math.cos(a) - (y2 - cy) * math.sin(a) + cx) + y3_new = int((x1 - cx) * math.sin(a) + (y2 - cy) * math.cos(a) + cy) + x4_new = int((x2 - cx) * math.cos(a) - (y1 - cy) * math.sin(a) + cx) + y4_new = int((x2 - cx) * math.sin(a) + (y1 - cy) * math.cos(a) + cy) + return [(x1_new, y1_new), (x3_new, y3_new), (x2_new, y2_new), (x4_new, y4_new)] + +def intersection(g, p): + g = Polygon(np.array(g).reshape(-1,2)) + p = Polygon(np.array(p).reshape(-1,2)) + if not g.is_valid or not p.is_valid: + return 0 + inter = g.intersection(p).area + union = g.area + p.area - inter + return 0 if union == 0 else inter / union + +def NMS(detectResult): + predBoxs = [] + sort_detectboxs = sorted(detectResult, key=lambda x: x.score, reverse=True) + for i in range(len(sort_detectboxs)): + if sort_detectboxs[i].classId == -1: + continue + p1 = rotate_rectangle(sort_detectboxs[i].xmin, sort_detectboxs[i].ymin, + sort_detectboxs[i].xmax, sort_detectboxs[i].ymax, + sort_detectboxs[i].angle) + predBoxs.append(sort_detectboxs[i]) + for j in range(i + 1, len(sort_detectboxs)): + if sort_detectboxs[j].classId == sort_detectboxs[i].classId: + p2 = rotate_rectangle(sort_detectboxs[j].xmin, sort_detectboxs[j].ymin, + sort_detectboxs[j].xmax, sort_detectboxs[j].ymax, + sort_detectboxs[j].angle) + if intersection(p1, p2) > nmsThresh: + sort_detectboxs[j].classId = -1 + return predBoxs + +def sigmoid(x): + return np.where(x >= 0, 1 / (1 + np.exp(-x)), np.exp(x) / (1 + np.exp(x))) + +def softmax(x, axis=-1): + exp_x = np.exp(x - np.max(x, axis=axis, keepdims=True)) + return exp_x / np.sum(exp_x, axis=axis, keepdims=True) + +def process(out, model_w, model_h, stride, angle_feature, index, scale_w=1, scale_h=1): + class_num = len(CLASSES) + angle_feature = angle_feature.reshape(-1) + xywh = out[:, :64, :] + conf = sigmoid(out[:, 64:, :]).reshape(-1) + boxes = [] + for ik in range(model_h * model_w * class_num): + if conf[ik] > objectThresh: + w = ik % model_w + h = (ik % (model_w * model_h)) // model_w + c = ik // (model_w * model_h) + # 解析xywh + xywh_ = xywh[0, :, (h * model_w) + w].reshape(1, 4, 16, 1) + data = np.arange(16).reshape(1, 1, 16, 1) + xywh_ = softmax(xywh_, 2) + xywh_ = np.sum(xywh_ * data, axis=2).reshape(-1) + xywh_add = xywh_[:2] + xywh_[2:] + xywh_sub = (xywh_[2:] - xywh_[:2]) / 2 + # 安全取角度 + angle_idx = min(index + (h * model_w) + w, len(angle_feature) - 1) + angle = (angle_feature[angle_idx] - 0.25) * math.pi + cos_a, sin_a = math.cos(angle), math.sin(angle) + xy = xywh_sub[0] * cos_a - xywh_sub[1] * sin_a, xywh_sub[0] * sin_a + xywh_sub[1] * cos_a + xywh1 = np.array([xy[0] + w + 0.5, xy[1] + h + 0.5, xywh_add[0], xywh_add[1]]) + xywh1 *= stride + xmin = (xywh1[0] - xywh1[2]/2) * scale_w + ymin = (xywh1[1] - xywh1[3]/2) * scale_h + xmax = (xywh1[0] + xywh1[2]/2) * scale_w + ymax = (xywh1[1] + xywh1[3]/2) * scale_h + boxes.append(DetectBox(c, conf[ik], xmin, ymin, xmax, ymax, angle)) + return boxes + +# ------------------- 主函数 ------------------- +def detect_boxes_angle_rknn(model_path, image_path, save_path=None): + img = cv2.imread(image_path) + if img is None: + print(f"❌ 无法读取图像: {image_path}") + return None, None + + img_resized, scale, offset_x, offset_y = letterbox_resize(img, (640, 640)) + infer_img = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB) + infer_img = np.expand_dims(infer_img, 0) + + rknn_lite = RKNNLite(verbose=False) + rknn_lite.load_rknn(model_path) + rknn_lite.init_runtime(core_mask=RKNNLite.NPU_CORE_0) + + results = rknn_lite.inference([infer_img]) + detect_boxes = [] + for x in results[:-1]: + index, stride = 0, 0 + if x.shape[2] == 20: + stride, index = 32, 20*4*20*4 + 20*2*20*2 + elif x.shape[2] == 40: + stride, index = 16, 20*4*20*4 + elif x.shape[2] == 80: + stride, index = 8, 0 + feature = x.reshape(1, 65, -1) + detect_boxes += process(feature, x.shape[3], x.shape[2], stride, results[-1], index) + + detect_boxes = NMS(detect_boxes) + + # 输出每个检测框角度 + for i, box in enumerate(detect_boxes): + print(f"框 {i+1}: angle = {box.angle:.4f} rad ({np.degrees(box.angle):.2f}°)") + if save_path: + xmin = int((box.xmin - offset_x)/scale) + ymin = int((box.ymin - offset_y)/scale) + xmax = int((box.xmax - offset_x)/scale) + ymax = int((box.ymax - offset_y)/scale) + points = rotate_rectangle(xmin, ymin, xmax, ymax, box.angle) + cv2.polylines(img, [np.array(points, np.int32)], True, (0, 255, 0), 1) + cv2.putText(img, f"{np.degrees(box.angle):.1f}°", (xmin, ymin-5), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1) + + if save_path: + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, img) + print(f"✅ 带角度的检测结果已保存到 {save_path}") + + rknn_lite.release() + return detect_boxes, img + +# ------------------- 使用示例 ------------------- +if __name__ == "__main__": + model_path = "obb.rknn" + image_path = "2.jpg" + save_path = "./inference_results/boxes_with_angle.jpg" + os.makedirs(os.path.dirname(save_path), exist_ok=True) + detect_boxes_angle_rknn(model_path, image_path, save_path) + diff --git a/ailai_pc/best.pt b/ailai_pc/best.pt new file mode 100644 index 0000000..a9e6a58 Binary files /dev/null and b/ailai_pc/best.pt differ diff --git a/ailai_pc/bushu_angle.py b/ailai_pc/bushu_angle.py new file mode 100644 index 0000000..891ee62 --- /dev/null +++ b/ailai_pc/bushu_angle.py @@ -0,0 +1,197 @@ + +import cv2 +import numpy as np +import math +from shapely.geometry import Polygon +from rknnlite.api import RKNNLite +import os + +# ------------------- 配置 ------------------- +CLASSES = ['clamp'] +nmsThresh = 0.4 +objectThresh = 0.5 + +# ------------------- 全局原图尺寸 ------------------- +ORIG_W = 2560 # 原图宽 +ORIG_H = 1440 # 原图高 + +# ------------------- 工具函数 ------------------- +def letterbox_resize(image, size, bg_color=114): + target_width, target_height = size + image_height, image_width, _ = image.shape + scale = min(target_width / image_width, target_height / image_height) + new_width, new_height = int(image_width * scale), int(image_height * scale) + image_resized = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA) + canvas = np.ones((target_height, target_width, 3), dtype=np.uint8) * bg_color + offset_x, offset_y = (target_width - new_width) // 2, (target_height - new_height) // 2 + canvas[offset_y:offset_y + new_height, offset_x:offset_x + new_width] = image_resized + return canvas, scale, offset_x, offset_y + +class DetectBox: + def __init__(self, classId, score, xmin, ymin, xmax, ymax, angle): + self.classId = classId + self.score = score + self.xmin = xmin + self.ymin = ymin + self.xmax = xmax + self.ymax = ymax + self.angle = angle + +def rotate_rectangle(x1, y1, x2, y2, a): + cx, cy = (x1 + x2) / 2, (y1 + y2) / 2 + x1_new = int((x1 - cx) * math.cos(a) - (y1 - cy) * math.sin(a) + cx) + y1_new = int((x1 - cx) * math.sin(a) + (y1 - cy) * math.cos(a) + cy) + x2_new = int((x2 - cx) * math.cos(a) - (y2 - cy) * math.sin(a) + cx) + y2_new = int((x2 - cx) * math.sin(a) + (y2 - cy) * math.cos(a) + cy) + x3_new = int((x1 - cx) * math.cos(a) - (y2 - cy) * math.sin(a) + cx) + y3_new = int((x1 - cx) * math.sin(a) + (y2 - cy) * math.cos(a) + cy) + x4_new = int((x2 - cx) * math.cos(a) - (y1 - cy) * math.sin(a) + cx) + y4_new = int((x2 - cx) * math.sin(a) + (y1 - cy) * math.cos(a) + cy) + return [(x1_new, y1_new), (x3_new, y3_new), (x2_new, y2_new), (x4_new, y4_new)] + +def intersection(g, p): + g = Polygon(np.array(g).reshape(-1,2)) + p = Polygon(np.array(p).reshape(-1,2)) + if not g.is_valid or not p.is_valid: + return 0 + inter = g.intersection(p).area + union = g.area + p.area - inter + return 0 if union == 0 else inter / union + +def NMS(detectResult): + predBoxs = [] + sort_detectboxs = sorted(detectResult, key=lambda x: x.score, reverse=True) + for i in range(len(sort_detectboxs)): + if sort_detectboxs[i].classId == -1: + continue + p1 = rotate_rectangle(sort_detectboxs[i].xmin, sort_detectboxs[i].ymin, + sort_detectboxs[i].xmax, sort_detectboxs[i].ymax, + sort_detectboxs[i].angle) + predBoxs.append(sort_detectboxs[i]) + for j in range(i + 1, len(sort_detectboxs)): + if sort_detectboxs[j].classId == sort_detectboxs[i].classId: + p2 = rotate_rectangle(sort_detectboxs[j].xmin, sort_detectboxs[j].ymin, + sort_detectboxs[j].xmax, sort_detectboxs[j].ymax, + sort_detectboxs[j].angle) + if intersection(p1, p2) > nmsThresh: + sort_detectboxs[j].classId = -1 + return predBoxs + +def sigmoid(x): + return np.where(x >= 0, 1 / (1 + np.exp(-x)), np.exp(x) / (1 + np.exp(x))) + +def softmax(x, axis=-1): + exp_x = np.exp(x - np.max(x, axis=axis, keepdims=True)) + return exp_x / np.sum(exp_x, axis=axis, keepdims=True) + +# ------------------- 关键修改:process函数加入scale ------------------- +def process(out, model_w, model_h, stride, angle_feature, index, scale=1.0, offset_x=0, offset_y=0): + class_num = len(CLASSES) + angle_feature = angle_feature.reshape(-1) + xywh = out[:, :64, :] + conf = sigmoid(out[:, 64:, :]).reshape(-1) + boxes = [] + for ik in range(model_h * model_w * class_num): + if conf[ik] > objectThresh: + w = ik % model_w + h = (ik % (model_w * model_h)) // model_w + c = ik // (model_w * model_h) + # 解析xywh + xywh_ = xywh[0, :, (h * model_w) + w].reshape(1, 4, 16, 1) + xywh_ = softmax(xywh_, 2) + data = np.arange(16).reshape(1, 1, 16, 1) + xywh_ = np.sum(xywh_ * data, axis=2).reshape(-1) + xywh_add = xywh_[:2] + xywh_[2:] + xywh_sub = (xywh_[2:] - xywh_[:2]) / 2 + # 取角度 + angle_idx = min(index + (h * model_w) + w, len(angle_feature) - 1) + angle = (angle_feature[angle_idx] - 0.25) * math.pi + cos_a, sin_a = math.cos(angle), math.sin(angle) + xy = xywh_sub[0] * cos_a - xywh_sub[1] * sin_a, xywh_sub[0] * sin_a + xywh_sub[1] * cos_a + xywh1 = np.array([xy[0] + w + 0.5, xy[1] + h + 0.5, xywh_add[0], xywh_add[1]]) + xywh1 *= stride + # 映射回原图坐标 + xmin = (xywh1[0] - xywh1[2]/2 - offset_x) / scale + ymin = (xywh1[1] - xywh1[3]/2 - offset_y) / scale + xmax = (xywh1[0] + xywh1[2]/2 - offset_x) / scale + ymax = (xywh1[1] + xywh1[3]/2 - offset_y) / scale + boxes.append(DetectBox(c, conf[ik], xmin, ymin, xmax, ymax, angle)) + return boxes + +# ------------------- 新可调用函数 ------------------- +def detect_boxes_rknn(model_path, image_path): + img = cv2.imread(image_path) + if img is None: + print(f"❌ 无法读取图像: {image_path}") + return None, None + + img_resized, scale, offset_x, offset_y = letterbox_resize(img, (640, 640)) + infer_img = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB) + infer_img = np.expand_dims(infer_img, 0) + + rknn_lite = RKNNLite(verbose=False) + rknn_lite.load_rknn(model_path) + rknn_lite.init_runtime(core_mask=RKNNLite.NPU_CORE_0) + + results = rknn_lite.inference([infer_img]) + detect_boxes = [] + for x in results[:-1]: + index, stride = 0, 0 + if x.shape[2] == 20: + stride, index = 32, 20*4*20*4 + 20*2*20*2 + elif x.shape[2] == 40: + stride, index = 16, 20*4*20*4 + elif x.shape[2] == 80: + stride, index = 8, 0 + feature = x.reshape(1, 65, -1) + detect_boxes += process(feature, x.shape[3], x.shape[2], stride, results[-1], index, + scale=scale, offset_x=offset_x, offset_y=offset_y) + + detect_boxes = NMS(detect_boxes) + rknn_lite.release() + return detect_boxes, img + +# ------------------- 绘制与辅助函数 ------------------- +def get_angles(detect_boxes): + return [box.angle for box in detect_boxes] + +def draw_boxes(img, detect_boxes, save_path=None): + for box in detect_boxes: + points = rotate_rectangle(box.xmin, box.ymin, box.xmax, box.ymax, box.angle) + cv2.polylines(img, [np.array(points, np.int32)], True, (0, 255, 0), 1) + cv2.putText(img, f"{np.degrees(box.angle):.1f}°", (int(box.xmin), int(box.ymin)-5), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1) + if save_path: + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, img) + print(f"✅ 带角度的检测结果已保存到 {save_path}") + return img + +def visualize_top_box(img, detect_boxes, save_path=None): + if not detect_boxes: + return img + top_box = max(detect_boxes, key=lambda x: x.score) + points = rotate_rectangle(top_box.xmin, top_box.ymin, top_box.xmax, top_box.ymax, top_box.angle) + cv2.polylines(img, [np.array(points, np.int32)], True, (0, 255, 0), 2) + cv2.putText(img, f"{np.degrees(top_box.angle):.1f}°", (int(top_box.xmin), int(top_box.ymin)-5), + cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2) + if save_path: + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, img) + return img + +# ------------------- 使用示例 ------------------- +if __name__ == "__main__": + model_path = "obb.rknn" + image_path = "2.jpg" + + detect_boxes, img = detect_boxes_rknn(model_path, image_path) + angles = get_angles(detect_boxes) + for i, angle in enumerate(angles): + print(f"框 {i+1}: angle = {angle:.4f} rad ({np.degrees(angle):.2f}°)") + + save_path_all = "./inference_results/boxes_all.jpg" + draw_boxes(img.copy(), detect_boxes, save_path_all) + + save_path_top = "./inference_results/top_box.jpg" + visualize_top_box(img.copy(), detect_boxes, save_path_top) diff --git a/ailai_pc/caculate_center.py b/ailai_pc/caculate_center.py new file mode 100644 index 0000000..5cfc0a9 --- /dev/null +++ b/ailai_pc/caculate_center.py @@ -0,0 +1,145 @@ +from ultralytics import YOLO +import cv2 +import os +import numpy as np + +# 设置类别名称(必须与训练时一致) +CLASS_NAMES = ['ban', 'bag'] # ✅ 确保顺序正确,对应模型的 class_id +COLORS = [(0, 255, 0), (255, 0, 0)] # ban: 绿色, bag: 蓝色 + + +def get_best_angles_per_class(image_path, weight_path, return_degree=False): + """ + 输入: + image_path: 图像路径 + weight_path: YOLO OBB 权重路径 + return_degree: 是否返回角度(单位:度),否则为弧度 + 输出: + 字典:{ class_name: best_angle 或 None } + """ + img = cv2.imread(image_path) + if img is None: + print(f"❌ 无法读取图像:{image_path}") + return {cls: None for cls in CLASS_NAMES} + + model = YOLO(weight_path) + results = model(img, save=False, imgsz=640, conf=0.15, task='obb') + result = results[0] + + boxes = result.obb + if boxes is None or len(boxes) == 0: + print("⚠️ 未检测到任何目标。") + return {cls: None for cls in CLASS_NAMES} + + # 提取数据 + xywhr = boxes.xywhr.cpu().numpy() # (N, 5) -> cx, cy, w, h, r (弧度) + confs = boxes.conf.cpu().numpy() # (N,) + class_ids = boxes.cls.cpu().numpy().astype(int) # (N,) + + # 初始化结果字典 + best_angles = {cls: None for cls in CLASS_NAMES} + + # 对每个类别找置信度最高的框 + for class_id, class_name in enumerate(CLASS_NAMES): + mask = (class_ids == class_id) + if not np.any(mask): + print(f"🟡 未检测到类别: {class_name}") + continue + + # 找该类别中置信度最高的 + idx_in_class = np.argmax(confs[mask]) + global_idx = np.where(mask)[0][idx_in_class] + angle_rad = xywhr[global_idx][4] + + best_angles[class_name] = np.degrees(angle_rad) if return_degree else angle_rad + + return best_angles + + +def save_obb_visual(image_path, weight_path, save_path): + """ + 输入: + image_path: 图像路径 + weight_path: YOLO权重路径 + save_path: 保存带标注图像路径 + 功能: + 检测所有 OBB,绘制框、类别名、旋转角度,保存图片 + """ + img = cv2.imread(image_path) + if img is None: + print(f"❌ 无法读取图像:{image_path}") + return + + model = YOLO(weight_path) + results = model(img, save=False, imgsz=640, conf=0.15, task='obb') + result = results[0] + + boxes = result.obb + if boxes is None or len(boxes) == 0: + print("⚠️ 未检测到任何目标。") + # 仍保存原图 + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, img) + return + + # 提取信息 + xywhr = boxes.xywhr.cpu().numpy() + confs = boxes.conf.cpu().numpy() + class_ids = boxes.cls.cpu().numpy().astype(int) + + # 绘制 + annotated_img = img.copy() + for i in range(len(boxes)): + cx, cy, w, h, r = xywhr[i] + angle_deg = np.degrees(r) + class_id = class_ids[i] + class_name = CLASS_NAMES[class_id] if class_id < len(CLASS_NAMES) else f"cls{class_id}" + conf = confs[i] + color = COLORS[class_id % len(COLORS)] if class_id < len(CLASS_NAMES) else (128, 128, 128) + + # 绘制旋转框 + rect = ((cx, cy), (w, h), angle_deg) + box_pts = cv2.boxPoints(rect).astype(int) + cv2.polylines(annotated_img, [box_pts], isClosed=True, color=color, thickness=2) + + # 标注文本:类别 + 置信度 + 角度 + text = f"{class_name} {conf:.2f} {angle_deg:.1f}°" + font_scale = 0.7 + thickness = 2 + text_size, _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, font_scale, thickness) + + # 文本背景 + cv2.rectangle(annotated_img, + (box_pts[0][0], box_pts[0][1] - text_size[1] - 8), + (box_pts[0][0] + text_size[0], box_pts[0][1] + 2), + color, -1) + # 文本 + cv2.putText(annotated_img, text, + (box_pts[0][0], box_pts[0][1] - 5), + cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255, 255, 255), thickness) + + # 保存 + os.makedirs(os.path.dirname(save_path), exist_ok=True) + cv2.imwrite(save_path, annotated_img) + print(f"✅ 检测结果已保存至: {save_path}") + + +# =============================== +# 示例调用 +# =============================== +if __name__ == "__main__": + weight = r"/home/hx/yolo/ultralytics_yolo11-main/runs/train/exp_obb_ailai/weights/best.pt" + image = r"/home/hx/yolo/ailai_obb/camera01/1.jpg" + save_path = "./inference_results/visualized_2.jpg" + + # 获取每个类别的最佳角度(以度为单位) + angles_deg = get_best_angles_per_class(image, weight, return_degree=True) + print("\n🎯 各类别最佳旋转角度(度):") + for cls_name, angle in angles_deg.items(): + if angle is not None: + print(f" {cls_name}: {angle:.2f}°") + else: + print(f" {cls_name}: 未检测到") + + # 可视化所有检测结果 + save_obb_visual(image, weight, save_path) \ No newline at end of file diff --git a/ailai_pc/caculate_xiangsu.py b/ailai_pc/caculate_xiangsu.py new file mode 100644 index 0000000..aa235ef --- /dev/null +++ b/ailai_pc/caculate_xiangsu.py @@ -0,0 +1,51 @@ +import cv2 + +# 全局变量 +refPt = [] +drawing = False + + +def draw_line(event, x, y, flags, param): + global refPt, drawing, image + + # 鼠标左键按下时,记录起始点坐标并开始绘制 + if event == cv2.EVENT_LBUTTONDOWN: + refPt = [(x, y)] + drawing = True + + # 当鼠标移动且处于绘制状态时,更新图像以显示当前的线段 + elif event == cv2.EVENT_MOUSEMOVE and drawing: + temp_image = image.copy() + cv2.line(temp_image, refPt[0], (x, y), (0, 255, 0), 2) + cv2.imshow("Image", temp_image) + + # 鼠标左键释放时,记录终点坐标,结束绘制并计算线段长度 + elif event == cv2.EVENT_LBUTTONUP: + refPt.append((x, y)) + drawing = False + # 在图像上画线 + cv2.line(image, refPt[0], refPt[1], (0, 255, 0), 2) + cv2.imshow("Image", image) + + # 计算线段长度 + dx = refPt[1][0] - refPt[0][0] + dy = refPt[1][1] - refPt[0][1] + length = (dx ** 2 + dy ** 2) ** 0.5 + print(f"线段长度: {length:.2f} 像素") + + +# 加载图像 +image_path = 'your_image_path_here.jpg' # 替换为你的图像路径 +image = cv2.imread(image_path) +cv2.namedWindow("Image") +cv2.setMouseCallback("Image", draw_line) + +while True: + cv2.imshow("Image", image) + key = cv2.waitKey(1) & 0xFF + + # 按下 'q' 键退出循环 + if key == ord('q'): + break + +cv2.destroyAllWindows() \ No newline at end of file diff --git a/ailai_pc/caculatet.py b/ailai_pc/caculatet.py new file mode 100644 index 0000000..c4c467b --- /dev/null +++ b/ailai_pc/caculatet.py @@ -0,0 +1,40 @@ +import cv2 +import numpy as np + +# 全局变量 +points = [] +drawing = False # 是否开始绘图 + + +def select_point(event, x, y, flags, param): + global drawing, points + + if event == cv2.EVENT_LBUTTONDOWN: + # 当鼠标左键按下时记录第一个点 + drawing = True + points = [(x, y)] + elif event == cv2.EVENT_LBUTTONUP: + # 当鼠标左键释放时记录第二个点,并完成线段的选择 + drawing = False + points.append((x, y)) + # 绘制线段 + cv2.line(img, points[0], points[1], (0, 255, 0), 2) + # 计算两点间的距离 + distance = np.sqrt((points[1][0] - points[0][0]) ** 2 + (points[1][1] - points[0][1]) ** 2) + print(f"线段的长度为: {distance:.2f} 像素") + # 显示更新后的图像 + cv2.imshow('image', img) + + +img_path = '/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/point1/val/192.168.0.234_01_20251014154410130.jpg' # 替换为你的图片路径 +img = cv2.imread(img_path) +cv2.namedWindow('image') +cv2.setMouseCallback('image', select_point) + +while(1): + cv2.imshow('image', img) + k = cv2.waitKey(1) & 0xFF + if k == 27: # 按下ESC退出 + break + +cv2.destroyAllWindows() \ No newline at end of file diff --git a/ailai_pc/camera01/1.jpg b/ailai_pc/camera01/1.jpg new file mode 100644 index 0000000..e1749d0 Binary files /dev/null and b/ailai_pc/camera01/1.jpg differ diff --git a/ailai_pc/camera01/2.jpg b/ailai_pc/camera01/2.jpg new file mode 100644 index 0000000..5065644 Binary files /dev/null and b/ailai_pc/camera01/2.jpg differ diff --git a/ailai_pc/camera01/3.jpg b/ailai_pc/camera01/3.jpg new file mode 100644 index 0000000..de1561e Binary files /dev/null and b/ailai_pc/camera01/3.jpg differ diff --git a/ailai_pc/camera01/4.jpg b/ailai_pc/camera01/4.jpg new file mode 100644 index 0000000..e914314 Binary files /dev/null and b/ailai_pc/camera01/4.jpg differ diff --git a/ailai_pc/cover_image.py b/ailai_pc/cover_image.py new file mode 100644 index 0000000..7292321 --- /dev/null +++ b/ailai_pc/cover_image.py @@ -0,0 +1,41 @@ +import os +import shutil + +def overwrite_images(folder1, folder2): + """ + 在 folder1 和 folder2 中查找同名图片, + 用 folder1 的图片覆盖 folder2 中的同名图片。 + """ + # 确保两个路径存在 + if not os.path.exists(folder1) or not os.path.exists(folder2): + print("❌ 输入的文件夹路径不存在") + return + + # 获取 folder1 所有文件 + files1 = set(os.listdir(folder1)) + files2 = set(os.listdir(folder2)) + + # 找出交集(相同名字的文件) + common_files = files1 & files2 + + if not common_files: + print("⚠️ 没有找到同名文件") + return + + for file in common_files: + src = os.path.join(folder1, file) + dst = os.path.join(folder2, file) + + # 仅处理图片文件(可根据需要扩展) + if src.lower().endswith((".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff")): + shutil.copy2(src, dst) + print(f"✅ 已覆盖: {dst}") + + print("🎯 覆盖完成!") + + +if __name__ == "__main__": + folder1 = r"/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/classdata1/save/class4" # 源文件夹 + folder2 = r"/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/seg/resize_seg2/train" # 目标文件夹 + + overwrite_images(folder1, folder2) diff --git a/ailai_pc/diff.py b/ailai_pc/diff.py new file mode 100644 index 0000000..87fee12 --- /dev/null +++ b/ailai_pc/diff.py @@ -0,0 +1,174 @@ +import cv2 +import numpy as np +from ultralytics import YOLO + +# ====================== 用户配置 ====================== +MODEL_PATH = 'best.pt' +IMAGE_PATH = '/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/point2/train/1.jpg' # 👈 修改为你的具体图像路径 +OUTPUT_DIR = './output_images' + +# 固定点(例如标定得到的理论位置) +FIXED_REF_POINT = (535.0, 605)# (x, y),单位:像素 +def calculate_scale(width_mm, width_px): + """ + 计算缩放因子(单位:mm/px) + :param width_mm: 实际宽度(单位:毫米) + :param width_px: 宽度的像素数量 + :return: 缩放因子(单位:mm/px) + """ + if width_px == 0: + print("像素宽度不能为0") + return None + return width_mm / float(width_px) + +# 示例使用: +# 假设我们知道一个参考物体的实际宽度是50毫米,在图像中占据100个像素 +width_mm = 70.0 # 实际宽度(单位:毫米) +width_px = 42 # 在图像中的宽度(单位:像素) + +SCALE_X= calculate_scale(width_mm, width_px) +print(f"水平方向的缩放因子为: {SCALE_X:.3f} mm/px") + +def calculate_scale_y(height_mm, height_px): + """ + 计算垂直方向的缩放因子(单位:mm/px) + :param height_mm: 实际高度(单位:毫米) + :param height_px: 高度的像素数量 + :return: 缩放因子(单位:mm/px) + """ + if height_px == 0: + print("像素高度不能为0") + return None + return height_mm / float(height_px) + +# 同样地,对于高度来说 +height_mm = 890.0 # 实际高度(单位:毫米) +height_px = 507 # 在图像中的高度(单位:像素) + +SCALE_Y = calculate_scale_y(height_mm, height_px) +print(f"垂直方向的缩放因子为: {SCALE_Y:.3f} mm/px") +# 创建输出目录 +import os +os.makedirs(OUTPUT_DIR, exist_ok=True) + +# ====================== 可视化函数(增强版)====================== +def draw_keypoints_and_offset(image, kpts_xy, kpts_conf, orig_shape, fixed_point, scale_x, scale_y): + """ + 在图像上绘制关键点、中心点、参考点、偏移箭头和文本 + :param image: OpenCV 图像 + :param kpts_xy: (N, K, 2) 坐标 + :param kpts_conf: (N, K) 置信度 + :param orig_shape: 原图尺寸 (H, W) + :param fixed_point: 固定参考点 (fx, fy) + :param scale_x: x方向缩放 mm/px + :param scale_y: y方向缩放 mm/px + :return: 处理后的图像,偏移信息列表 + """ + colors = [(0, 0, 255), (255, 0, 0), (0, 255, 0), (255, 255, 0)] # 1红, 2蓝, 3绿, 4青 + results_info = [] + + for i in range(len(kpts_xy)): + xy = kpts_xy[i] # (K, 2) + conf = kpts_conf[i] if kpts_conf.ndim == 2 else kpts_conf[i:i+1] + + # 检查是否有至少两个关键点 + if len(xy) < 2: + print(f"⚠️ 实例 {i} 的关键点数量不足2个") + continue + + p1 = xy[0] # 第一个关键点 + p2 = xy[1] # 第二个关键点 + + c1 = conf[0] if hasattr(conf, '__len__') else conf + c2 = conf[1] if hasattr(conf, '__len__') else conf + if c1 < 0.5 or c2 < 0.5: + print(f"⚠️ 实例 {i} 的前两个关键点置信度过低: c1={c1:.3f}, c2={c2:.3f}") + continue + + # 转为整数坐标(仅用于绘制) + p1_int = tuple(map(int, p1)) + p2_int = tuple(map(int, p2)) + + h, w = orig_shape + valid = all(0 <= x < w and 0 <= y < h for x, y in [p1, p2]) + if not valid: + print(f"⚠️ 实例 {i} 的关键点超出图像边界") + continue + + # 绘制前两个关键点 + cv2.circle(image, p1_int, radius=15, color=colors[0], thickness=-1) # 红色 + cv2.circle(image, p2_int, radius=15, color=colors[1], thickness=-1) # 蓝色 + + # 标注编号 + cv2.putText(image, "1", (p1_int[0] + 20, p1_int[1] - 20), + cv2.FONT_HERSHEY_SIMPLEX, 1.5, colors[0], 5) + cv2.putText(image, "2", (p2_int[0] + 20, p2_int[1] - 20), + cv2.FONT_HERSHEY_SIMPLEX, 1.5, colors[1], 5) + + center_x = (p1[0] + p2[0]) / 2.0 + center_y = (p1[1] + p2[1]) / 2.0 + dynamic_center = (int(center_x), int(center_y)) + + cv2.circle(image, dynamic_center, radius=18, color=(0, 255, 0), thickness=3) + cv2.putText(image, "Center", (dynamic_center[0] + 30, dynamic_center[1]), + cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 3) + + fx, fy = map(int, fixed_point) + cv2.circle(image, (fx, fy), radius=20, color=(255, 255, 0), thickness=3) + cv2.putText(image, "Ref", (fx + 30, fy), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255, 255, 0), 3) + + dx_px = center_x - fixed_point[0] + dy_px = center_y - fixed_point[1] + dx_mm = dx_px * scale_x + dy_mm = dy_px * scale_y + + cv2.arrowedLine(image, (fx, fy), dynamic_center, (0, 255, 255), 3, tipLength=0.05) + + cv2.putText(image, f"ΔX={dx_mm:+.1f}mm", (fx + 40, fy - 40), + cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 255), 3) + cv2.putText(image, f"ΔY={dy_mm:+.1f}mm", (fx + 40, fy + 40), + cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 255), 3) + + results_info.append({ + 'instance': i, + 'center': (center_x, center_y), + 'dx_px': dx_px, 'dy_px': dy_px, + 'dx_mm': dx_mm, 'dy_mm': dy_mm + }) + + return image, results_info + + +if __name__ == "__main__": + img = cv2.imread(IMAGE_PATH) + if img is None: + print(f"❌ 无法读取图像,检查路径: {IMAGE_PATH}") + exit(1) + + model = YOLO(MODEL_PATH) + results = model(img) + + for i, result in enumerate(results): + if result.keypoints is not None: + kpts = result.keypoints + orig_shape = kpts.orig_shape + + kpts_xy = kpts.xy.cpu().numpy() + kpts_conf = kpts.conf.cpu().numpy() if kpts.conf is not None else np.ones(kpts_xy.shape[:2]) + + img_with_kpts = img.copy() + + img_with_kpts, offset_results = draw_keypoints_and_offset( + img_with_kpts, kpts_xy, kpts_conf, orig_shape, + fixed_point=FIXED_REF_POINT, + scale_x=SCALE_X, scale_y=SCALE_Y + ) + + for info in offset_results: + print(f" 📌 实例 {info['instance']}: " + f"ΔX={info['dx_mm']:+.2f}mm, ΔY={info['dy_mm']:+.2f}mm") + + save_filename = f"offset_{os.path.basename(IMAGE_PATH)}" + save_path = os.path.join(OUTPUT_DIR, save_filename) + cv2.imwrite(save_path, img_with_kpts) + print(f" 💾 结果已保存: {save_path}") \ No newline at end of file diff --git a/ailai_pc/inference_results/1.jpg b/ailai_pc/inference_results/1.jpg new file mode 100644 index 0000000..99053bd Binary files /dev/null and b/ailai_pc/inference_results/1.jpg differ diff --git a/ailai_pc/inference_results/2.jpg b/ailai_pc/inference_results/2.jpg new file mode 100644 index 0000000..a3c9e66 Binary files /dev/null and b/ailai_pc/inference_results/2.jpg differ diff --git a/ailai_pc/inference_results/3.jpg b/ailai_pc/inference_results/3.jpg new file mode 100644 index 0000000..453ba0d Binary files /dev/null and b/ailai_pc/inference_results/3.jpg differ diff --git a/ailai_pc/inference_results/4.jpg b/ailai_pc/inference_results/4.jpg new file mode 100644 index 0000000..c329c84 Binary files /dev/null and b/ailai_pc/inference_results/4.jpg differ diff --git a/ailai_pc/inference_results/bag_center.txt b/ailai_pc/inference_results/bag_center.txt new file mode 100644 index 0000000..664d82b --- /dev/null +++ b/ailai_pc/inference_results/bag_center.txt @@ -0,0 +1 @@ +617.1340942382812 225.45236206054688 diff --git a/ailai_pc/inference_results/ban_center.txt b/ailai_pc/inference_results/ban_center.txt new file mode 100644 index 0000000..664d82b --- /dev/null +++ b/ailai_pc/inference_results/ban_center.txt @@ -0,0 +1 @@ +617.1340942382812 225.45236206054688 diff --git a/ailai_pc/inference_results/best_center_vis_2.jpg b/ailai_pc/inference_results/best_center_vis_2.jpg new file mode 100644 index 0000000..8a63055 Binary files /dev/null and b/ailai_pc/inference_results/best_center_vis_2.jpg differ diff --git a/ailai_pc/output_images/offset_1.jpg b/ailai_pc/output_images/offset_1.jpg new file mode 100644 index 0000000..5899316 Binary files /dev/null and b/ailai_pc/output_images/offset_1.jpg differ diff --git a/ailai_pc/point.pt b/ailai_pc/point.pt new file mode 100644 index 0000000..133e9fe Binary files /dev/null and b/ailai_pc/point.pt differ diff --git a/ailai_pc/point_test.py b/ailai_pc/point_test.py new file mode 100644 index 0000000..1793fcb --- /dev/null +++ b/ailai_pc/point_test.py @@ -0,0 +1,129 @@ +import cv2 +import numpy as np +from ultralytics import YOLO +import os + +# ====================== 用户配置 ====================== +MODEL_PATH = 'best.pt' +IMAGE_SOURCE_DIR = './train' # 👈 修改为你的图像文件夹路径 +OUTPUT_DIR = './output_images' # 保存结果的文件夹 + +# 支持的图像扩展名 +IMG_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.bmp', '.tiff', '.tif', '.webp'} + +os.makedirs(OUTPUT_DIR, exist_ok=True) + +# ====================== 可视化函数 ====================== +def draw_keypoints_on_image(image, kpts_xy, kpts_conf, orig_shape): + """ + 在图像上绘制关键点 + :param image: OpenCV 图像 + :param kpts_xy: (N, K, 2) 坐标 + :param kpts_conf: (N, K) 置信度 + :param orig_shape: 原图尺寸 (H, W) + """ + colors = [(0, 0, 255), (255, 0, 0), (0, 255, 0), (255, 255, 0)] # 1红, 2蓝, 3绿, 4青 + + for i in range(len(kpts_xy)): + xy = kpts_xy[i] # (4, 2) + conf = kpts_conf[i] if kpts_conf.ndim == 2 else kpts_conf[i:i+1] # (4,) 或标量 + + for j in range(len(xy)): + x, y = xy[j] + c = conf[j] if hasattr(conf, '__len__') else conf + + x, y = int(x), int(y) + + # 检查坐标是否在图像范围内 + if x < 0 or y < 0 or x >= orig_shape[1] or y >= orig_shape[0]: + continue + + # 只绘制置信度 > 0.5 的点 + if c < 0.5: + continue + + # 绘制实心圆 + cv2.circle(image, (x, y), radius=15, color=colors[j], thickness=-1) + # 标注编号(偏移避免遮挡) + cv2.putText(image, f'{j+1}', (x + 20, y - 20), + cv2.FONT_HERSHEY_SIMPLEX, 1.5, colors[j], 5) + + return image + + +# ====================== 主程序 ====================== +if __name__ == "__main__": + print("🚀 开始批量关键点检测任务") + + # 加载模型 + print("🔄 加载 YOLO 模型...") + model = YOLO(MODEL_PATH) + print(f"✅ 模型加载完成: {MODEL_PATH}") + + # 获取所有图像文件 + image_files = [ + f for f in os.listdir(IMAGE_SOURCE_DIR) + if os.path.splitext(f.lower())[1] in IMG_EXTENSIONS + ] + + if not image_files: + print(f"❌ 错误:在 {IMAGE_SOURCE_DIR} 中未找到支持的图像文件") + exit(1) + + print(f"📁 发现 {len(image_files)} 张图像待处理") + + # 遍历每张图像 + for img_filename in image_files: + img_path = os.path.join(IMAGE_SOURCE_DIR, img_filename) + print(f"\n🖼️ 正在处理: {img_filename}") + + # 读取图像 + img = cv2.imread(img_path) + if img is None: + print(f"❌ 无法读取图像,跳过: {img_path}") + continue + print(f" ✅ 图像加载成功 (shape: {img.shape})") + + # 推理 + print(" 🔍 正在推理...") + results = model(img) + + processed = False # 标记是否处理了关键点 + + for i, result in enumerate(results): + if result.keypoints is not None: + kpts = result.keypoints + orig_shape = kpts.orig_shape # (H, W) + + # 获取坐标和置信度 + kpts_xy = kpts.xy.cpu().numpy() # (N, K, 2) + kpts_conf = kpts.conf.cpu().numpy() if kpts.conf is not None else np.ones(kpts_xy.shape[:2]) + + print(f" ✅ 检测到 {len(kpts_xy)} 个实例") + + # 绘制关键点 + img_with_kpts = draw_keypoints_on_image(img.copy(), kpts_xy, kpts_conf, orig_shape) + + # 保存图像 + save_filename = f"keypoints_{img_filename}" + save_path = os.path.join(OUTPUT_DIR, save_filename) + cv2.imwrite(save_path, img_with_kpts) + print(f" 💾 结果已保存: {save_path}") + + # 可选:显示图像(每次一张,按任意键继续) + # display_img = cv2.resize(img_with_kpts, (1280, 720)) + # cv2.imshow("Keypoints Detection", display_img) + # print(" ⌨️ 按任意键继续...") + # cv2.waitKey(0) + # cv2.destroyAllWindows() + + processed = True + + if not processed: + print(f" ❌ 未检测到关键点,跳过保存") + + print("\n" + "=" * 60) + print("🎉 批量推理完成!") + print(f"📊 总共处理 {len(image_files)} 张图像") + print(f"📁 结果保存在: {OUTPUT_DIR}") + print("=" * 60) \ No newline at end of file diff --git a/ailai_pc/rename_file.py b/ailai_pc/rename_file.py new file mode 100644 index 0000000..57d4f5a --- /dev/null +++ b/ailai_pc/rename_file.py @@ -0,0 +1,40 @@ +import os +import shutil + +# ================= 用户配置 ================= +FOLDER_PATH = '/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/point2' # 图片和 txt 所在文件夹 +IMG_EXT = '.jpg' +TXT_EXT = '.txt' +START_NUM = 1 # 从 1 开始编号 + +# ================= 获取文件列表 ================= +files = os.listdir(FOLDER_PATH) + +# 分别筛选图片和 txt +images = sorted([f for f in files if f.lower().endswith(IMG_EXT)]) +txts = sorted([f for f in files if f.lower().endswith(TXT_EXT)]) + +# 检查数量是否一致 +if len(images) != len(txts): + print(f"⚠️ 图片数量 ({len(images)}) 与 txt 文件数量 ({len(txts)}) 不一致!") + +# ================= 重命名 ================= +for idx, (img_file, txt_file) in enumerate(zip(images, txts), start=START_NUM): + img_new = f"{idx}{IMG_EXT}" + txt_new = f"{idx}{TXT_EXT}" + + # 原始完整路径 + img_path = os.path.join(FOLDER_PATH, img_file) + txt_path = os.path.join(FOLDER_PATH, txt_file) + + # 新路径 + img_new_path = os.path.join(FOLDER_PATH, img_new) + txt_new_path = os.path.join(FOLDER_PATH, txt_new) + + # 重命名(如果已经存在则覆盖) + shutil.move(img_path, img_new_path) + shutil.move(txt_path, txt_new_path) + + print(f"✅ {img_file} -> {img_new}, {txt_file} -> {txt_new}") + +print("🎉 全部文件重命名完成!") diff --git a/ailai_pc/rename_image.py b/ailai_pc/rename_image.py new file mode 100644 index 0000000..6f800bb --- /dev/null +++ b/ailai_pc/rename_image.py @@ -0,0 +1,56 @@ +import os +from pathlib import Path + +def rename_images_in_folder(folder_path): + # 支持的图片扩展名(不区分大小写) + image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'} + + # 转换为 Path 对象 + folder = Path(folder_path) + + # 检查文件夹是否存在 + if not folder.exists(): + print(f"❌ 文件夹不存在: {folder_path}") + return + + if not folder.is_dir(): + print(f"❌ 路径不是文件夹: {folder_path}") + return + + # 获取所有图片文件 + image_files = [f for f in folder.iterdir() + if f.is_file() and f.suffix.lower() in image_extensions] + + if not image_files: + print("🔍 文件夹中没有找到图片文件。") + return + + # 排序(按文件名排序,确保顺序一致) + image_files.sort() + + print(f"📁 正在处理文件夹: {folder}") + print(f"🖼️ 找到 {len(image_files)} 个图片文件") + + renamed_count = 0 + for idx, file_path in enumerate(image_files, start=1): + new_name = f"{idx}.jpg" # 统一输出为 .jpg 格式 + new_path = folder / new_name + + # 防止覆盖已存在的目标文件 + while new_path.exists(): + print(f"⚠️ {new_name} 已存在,跳过或改名?") + # 可以选择跳过,或用不同逻辑处理 + break + else: + file_path.rename(new_path) + print(f"✅ {file_path.name} → {new_name}") + renamed_count += 1 + + print(f"\n✅ 完成!共重命名 {renamed_count} 个文件。") + +# =========================== +# 🔧 使用这里:设置你的文件夹路径 +# =========================== +if __name__ == "__main__": + folder = r"/home/hx/下载/2025-09-24" # <-- 修改为你的图片文件夹路径 + rename_images_in_folder(folder) \ No newline at end of file diff --git a/ailai_pc/train/192.168.0.234_01_20251014144144937.jpg b/ailai_pc/train/192.168.0.234_01_20251014144144937.jpg new file mode 100644 index 0000000..9141761 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144144937.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144222222.jpg b/ailai_pc/train/192.168.0.234_01_20251014144222222.jpg new file mode 100644 index 0000000..d8c323f Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144222222.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144303840.jpg b/ailai_pc/train/192.168.0.234_01_20251014144303840.jpg new file mode 100644 index 0000000..2b40fc3 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144303840.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144341882.jpg b/ailai_pc/train/192.168.0.234_01_20251014144341882.jpg new file mode 100644 index 0000000..4d981d8 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144341882.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144421259.jpg b/ailai_pc/train/192.168.0.234_01_20251014144421259.jpg new file mode 100644 index 0000000..3f41d3d Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144421259.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144500393.jpg b/ailai_pc/train/192.168.0.234_01_20251014144500393.jpg new file mode 100644 index 0000000..34d51dc Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144500393.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144538968.jpg b/ailai_pc/train/192.168.0.234_01_20251014144538968.jpg new file mode 100644 index 0000000..ac86440 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144538968.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144619387.jpg b/ailai_pc/train/192.168.0.234_01_20251014144619387.jpg new file mode 100644 index 0000000..686be48 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144619387.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144814974.jpg b/ailai_pc/train/192.168.0.234_01_20251014144814974.jpg new file mode 100644 index 0000000..fded362 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144814974.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014144929890.jpg b/ailai_pc/train/192.168.0.234_01_20251014144929890.jpg new file mode 100644 index 0000000..0841f84 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014144929890.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014145006232.jpg b/ailai_pc/train/192.168.0.234_01_20251014145006232.jpg new file mode 100644 index 0000000..a5b4f5b Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014145006232.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014145045330.jpg b/ailai_pc/train/192.168.0.234_01_20251014145045330.jpg new file mode 100644 index 0000000..f74e1a4 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014145045330.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014145128164.jpg b/ailai_pc/train/192.168.0.234_01_20251014145128164.jpg new file mode 100644 index 0000000..13a9fb0 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014145128164.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014145244471.jpg b/ailai_pc/train/192.168.0.234_01_20251014145244471.jpg new file mode 100644 index 0000000..a231114 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014145244471.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014145321687.jpg b/ailai_pc/train/192.168.0.234_01_20251014145321687.jpg new file mode 100644 index 0000000..322f64e Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014145321687.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150210497.jpg b/ailai_pc/train/192.168.0.234_01_20251014150210497.jpg new file mode 100644 index 0000000..e160439 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150210497.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150246105.jpg b/ailai_pc/train/192.168.0.234_01_20251014150246105.jpg new file mode 100644 index 0000000..4632b44 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150246105.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150325231.jpg b/ailai_pc/train/192.168.0.234_01_20251014150325231.jpg new file mode 100644 index 0000000..75dd03b Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150325231.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150406560.jpg b/ailai_pc/train/192.168.0.234_01_20251014150406560.jpg new file mode 100644 index 0000000..3222f2f Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150406560.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150444617.jpg b/ailai_pc/train/192.168.0.234_01_20251014150444617.jpg new file mode 100644 index 0000000..4db12d2 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150444617.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_2025101415052359.jpg b/ailai_pc/train/192.168.0.234_01_2025101415052359.jpg new file mode 100644 index 0000000..fd8a6cc Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_2025101415052359.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150601333.jpg b/ailai_pc/train/192.168.0.234_01_20251014150601333.jpg new file mode 100644 index 0000000..bdb9a8b Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150601333.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150642365.jpg b/ailai_pc/train/192.168.0.234_01_20251014150642365.jpg new file mode 100644 index 0000000..9812532 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150642365.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150720686.jpg b/ailai_pc/train/192.168.0.234_01_20251014150720686.jpg new file mode 100644 index 0000000..46490dd Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150720686.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014150918102.jpg b/ailai_pc/train/192.168.0.234_01_20251014150918102.jpg new file mode 100644 index 0000000..4d0d8d9 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014150918102.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_2025101415103290.jpg b/ailai_pc/train/192.168.0.234_01_2025101415103290.jpg new file mode 100644 index 0000000..fa923d5 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_2025101415103290.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_2025101415111060.jpg b/ailai_pc/train/192.168.0.234_01_2025101415111060.jpg new file mode 100644 index 0000000..26ada89 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_2025101415111060.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014151150768.jpg b/ailai_pc/train/192.168.0.234_01_20251014151150768.jpg new file mode 100644 index 0000000..7be2d3a Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014151150768.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014151232368.jpg b/ailai_pc/train/192.168.0.234_01_20251014151232368.jpg new file mode 100644 index 0000000..da51dd3 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014151232368.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014151311222.jpg b/ailai_pc/train/192.168.0.234_01_20251014151311222.jpg new file mode 100644 index 0000000..0b0bfe2 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014151311222.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014151353357.jpg b/ailai_pc/train/192.168.0.234_01_20251014151353357.jpg new file mode 100644 index 0000000..20a047d Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014151353357.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_202510141514352.jpg b/ailai_pc/train/192.168.0.234_01_202510141514352.jpg new file mode 100644 index 0000000..e69faee Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_202510141514352.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_2025101415152183.jpg b/ailai_pc/train/192.168.0.234_01_2025101415152183.jpg new file mode 100644 index 0000000..b44e534 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_2025101415152183.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014151922555.jpg b/ailai_pc/train/192.168.0.234_01_20251014151922555.jpg new file mode 100644 index 0000000..f69e644 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014151922555.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153132629.jpg b/ailai_pc/train/192.168.0.234_01_20251014153132629.jpg new file mode 100644 index 0000000..ccf2994 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153132629.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153215762.jpg b/ailai_pc/train/192.168.0.234_01_20251014153215762.jpg new file mode 100644 index 0000000..4dbcba7 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153215762.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153257985.jpg b/ailai_pc/train/192.168.0.234_01_20251014153257985.jpg new file mode 100644 index 0000000..8f5c9d5 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153257985.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153338300.jpg b/ailai_pc/train/192.168.0.234_01_20251014153338300.jpg new file mode 100644 index 0000000..a66d909 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153338300.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153420611.jpg b/ailai_pc/train/192.168.0.234_01_20251014153420611.jpg new file mode 100644 index 0000000..4a04002 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153420611.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153506692.jpg b/ailai_pc/train/192.168.0.234_01_20251014153506692.jpg new file mode 100644 index 0000000..1d5ca4f Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153506692.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153632704.jpg b/ailai_pc/train/192.168.0.234_01_20251014153632704.jpg new file mode 100644 index 0000000..ee75f44 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153632704.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153800800.jpg b/ailai_pc/train/192.168.0.234_01_20251014153800800.jpg new file mode 100644 index 0000000..7f7dfd2 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153800800.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153839977.jpg b/ailai_pc/train/192.168.0.234_01_20251014153839977.jpg new file mode 100644 index 0000000..cd1f939 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153839977.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153918385.jpg b/ailai_pc/train/192.168.0.234_01_20251014153918385.jpg new file mode 100644 index 0000000..f582908 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153918385.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014153957167.jpg b/ailai_pc/train/192.168.0.234_01_20251014153957167.jpg new file mode 100644 index 0000000..b43fa95 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014153957167.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014154037360.jpg b/ailai_pc/train/192.168.0.234_01_20251014154037360.jpg new file mode 100644 index 0000000..3f30529 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014154037360.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014154121106.jpg b/ailai_pc/train/192.168.0.234_01_20251014154121106.jpg new file mode 100644 index 0000000..ca82513 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014154121106.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014154203390.jpg b/ailai_pc/train/192.168.0.234_01_20251014154203390.jpg new file mode 100644 index 0000000..87b6456 Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014154203390.jpg differ diff --git a/ailai_pc/train/192.168.0.234_01_20251014154328204.jpg b/ailai_pc/train/192.168.0.234_01_20251014154328204.jpg new file mode 100644 index 0000000..35263bc Binary files /dev/null and b/ailai_pc/train/192.168.0.234_01_20251014154328204.jpg differ diff --git a/ailai_pc/trans_cvattoobb.py b/ailai_pc/trans_cvattoobb.py new file mode 100644 index 0000000..e1758d2 --- /dev/null +++ b/ailai_pc/trans_cvattoobb.py @@ -0,0 +1,116 @@ +# pascal_robndbox_to_yolo_obb.py +import xml.etree.ElementTree as ET +import numpy as np +from pathlib import Path +import argparse + +def robndbox_to_yolo_obb(xml_path, output_dir, class_names): + """ + 将单个带有 的 Pascal VOC XML 转换为 YOLO-OBB 格式 .txt + """ + try: + tree = ET.parse(xml_path) + root = tree.getroot() + + # 获取图像尺寸 + width_elem = root.find("size/width") + height_elem = root.find("size/height") + if width_elem is None or height_elem is None: + print(f"❌ 跳过 {xml_path}: 缺少 size/width 或 size/height") + return + img_w = int(width_elem.text) + img_h = int(height_elem.text) + + if img_w == 0 or img_h == 0: + print(f"❌ 跳过 {xml_path}: 图像尺寸为 0") + return + + # 输出文件路径 + label_file = Path(output_dir) / "labels" / (Path(xml_path).stem + ".txt") + label_file.parent.mkdir(parents=True, exist_ok=True) + + lines = [] + for obj in root.findall("object"): + name = obj.find("name").text + if name not in class_names: + print(f"⚠️ 跳过未知类别: {name} (文件: {xml_path.name})") + continue + class_id = class_names.index(name) + + rb = obj.find("robndbox") + if rb is None: + print(f"⚠️ 跳过无 robndbox 的对象: {name}") + continue + + cx = float(rb.find("cx").text) + cy = float(rb.find("cy").text) + w = float(rb.find("w").text) + h = float(rb.find("h").text) + angle_deg = float(rb.find("angle").text) + + # 计算四个角点(相对于中心旋转) + angle_rad = np.radians(angle_deg) + cos_a, sin_a = np.cos(angle_rad), np.sin(angle_rad) + + corners = np.array([ + [-w/2, -h/2], + [ w/2, -h/2], + [ w/2, h/2], + [-w/2, h/2] + ]) + rotation_matrix = np.array([[cos_a, -sin_a], [sin_a, cos_a]]) + rotated_corners = np.dot(corners, rotation_matrix.T) + [cx, cy] + + # 归一化到 [0,1] + rotated_corners[:, 0] /= img_w + rotated_corners[:, 1] /= img_h + + # 展平并生成 YOLO-OBB 行 + coords = rotated_corners.flatten() + line = str(class_id) + " " + " ".join(f"{x:.6f}" for x in coords) + lines.append(line) + + # 只有存在有效标注才写入文件 + if lines: + with open(label_file, "w", encoding="utf-8") as f: + f.write("\n".join(lines) + "\n") + print(f"✅ 已生成: {label_file}") + else: + print(f"🟡 无有效标注,跳过生成: {label_file}") + + except Exception as e: + print(f"❌ 处理 {xml_path} 时出错: {e}") + + +def main(): + # ==================== 配置区 ==================== + # ✅ 修改以下路径和类别 + XML_DIR = "/home/hx/桌面/ailai_test/train" # 包含 .xml 文件的目录 + OUTPUT_DIR = "yolo_obb_dataset" # 输出目录 + CLASS_NAMES = ["ban", "bag"] # 你的类别列表,顺序即 class_id + # ============================================== + + xml_dir = Path(XML_DIR) + output_dir = Path(OUTPUT_DIR) + + if not xml_dir.exists(): + raise FileNotFoundError(f"未找到 XML 目录: {xml_dir}") + + # 查找所有 .xml 文件 + xml_files = list(xml_dir.glob("*.xml")) + if not xml_files: + print(f"⚠️ 在 {xml_dir} 中未找到 .xml 文件") + return + + print(f"🔍 找到 {len(xml_files)} 个 XML 文件") + print(f"📦 类别映射: { {i: name for i, name in enumerate(CLASS_NAMES)} }") + + # 批量转换 + for xml_file in xml_files: + robndbox_to_yolo_obb(xml_file, output_dir, CLASS_NAMES) + + print(f"\n🎉 转换完成!标签已保存至: {output_dir / 'labels'}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train.cache b/ailai_pc/yolo_obb_dataset/ailai_test/train.cache new file mode 100644 index 0000000..6f9abf6 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train.cache differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/1.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/1.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/1.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/1.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/1.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/1.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/10.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/10.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/10.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/10.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/10.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/10.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/11.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/11.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/11.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/11.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/11.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/11.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/12.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/12.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/12.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/12.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/12.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/12.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/2.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/2.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/2.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/2.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/2.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/2.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/3.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/3.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/3.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/3.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/3.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/3.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/4.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/4.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/4.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/4.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/4.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/4.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/5.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/5.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/5.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/5.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/5.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/5.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/6.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/6.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/6.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/6.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/6.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/6.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/7.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/7.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/7.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/7.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/7.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/7.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/8.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/8.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/8.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/8.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/8.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/8.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/9.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/train/9.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/train/9.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/train/9.txt b/ailai_pc/yolo_obb_dataset/ailai_test/train/9.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/train/9.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/val.cache b/ailai_pc/yolo_obb_dataset/ailai_test/val.cache new file mode 100644 index 0000000..cb0f535 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/val.cache differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/val/1.jpg b/ailai_pc/yolo_obb_dataset/ailai_test/val/1.jpg new file mode 100644 index 0000000..b6a6c2d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test/val/1.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test/val/1.txt b/ailai_pc/yolo_obb_dataset/ailai_test/val/1.txt new file mode 100644 index 0000000..d368f2e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test/val/1.txt @@ -0,0 +1,2 @@ +0 0.287799 0.126397 0.708264 0.166508 0.698037 0.505318 0.277572 0.465207 +1 0.405951 0.167969 0.626046 0.189171 0.618472 0.437663 0.398377 0.416461 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train.cache b/ailai_pc/yolo_obb_dataset/ailai_test1/train.cache new file mode 100644 index 0000000..6b081bd Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train.cache differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/093615_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/093615_Color.jpg new file mode 100644 index 0000000..914507d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/093615_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/093615_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/093615_Color.txt new file mode 100644 index 0000000..01f79ba --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/093615_Color.txt @@ -0,0 +1 @@ +0 0.284333 0.178383 0.700034 0.122815 0.713823 0.448839 0.298122 0.504407 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094130_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094130_Color.jpg new file mode 100644 index 0000000..5065644 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094130_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094130_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094130_Color.txt new file mode 100644 index 0000000..bb1a8b5 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094130_Color.txt @@ -0,0 +1,2 @@ +0 0.279006 0.177951 0.698267 0.121908 0.712393 0.455882 0.293131 0.511925 +1 0.322506 0.193800 0.549706 0.169096 0.558525 0.425436 0.331325 0.450140 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094244_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094244_Color.jpg new file mode 100644 index 0000000..3562784 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094244_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094244_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094244_Color.txt new file mode 100644 index 0000000..37781b2 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094244_Color.txt @@ -0,0 +1,2 @@ +0 0.281420 0.175105 0.700689 0.119060 0.714815 0.453034 0.295545 0.509079 +1 0.375245 0.190536 0.612882 0.166916 0.620872 0.420992 0.383235 0.444611 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094316_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094316_Color.jpg new file mode 100644 index 0000000..0e9cfb4 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094316_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094316_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094316_Color.txt new file mode 100644 index 0000000..b423905 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094316_Color.txt @@ -0,0 +1,2 @@ +0 0.281888 0.173424 0.701158 0.117380 0.715284 0.451367 0.296014 0.507412 +1 0.467663 0.181701 0.704471 0.159638 0.711766 0.407104 0.474958 0.429167 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094348_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094348_Color.jpg new file mode 100644 index 0000000..556ea78 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094348_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094348_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094348_Color.txt new file mode 100644 index 0000000..97d53f7 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094348_Color.txt @@ -0,0 +1,2 @@ +0 0.280474 0.176785 0.699744 0.120741 0.713869 0.454715 0.294600 0.510759 +1 0.368151 0.196284 0.603445 0.153057 0.618380 0.409980 0.383086 0.453207 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094401_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094401_Color.jpg new file mode 100644 index 0000000..629adfa Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094401_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094401_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094401_Color.txt new file mode 100644 index 0000000..615c383 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094401_Color.txt @@ -0,0 +1,2 @@ +0 0.282777 0.174770 0.702198 0.122630 0.715340 0.456730 0.295919 0.508870 +1 0.349052 0.244794 0.583194 0.147929 0.616128 0.399526 0.381985 0.496391 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094411_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094411_Color.jpg new file mode 100644 index 0000000..f56dccb Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094411_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094411_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094411_Color.txt new file mode 100644 index 0000000..6bf9e04 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094411_Color.txt @@ -0,0 +1,2 @@ +0 0.281419 0.178452 0.700689 0.122407 0.714815 0.456395 0.295545 0.512440 +1 0.346724 0.185278 0.578903 0.181676 0.580135 0.432750 0.347957 0.436352 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094419_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094419_Color.jpg new file mode 100644 index 0000000..c4742cf Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094419_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094419_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094419_Color.txt new file mode 100644 index 0000000..2e10efb --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094419_Color.txt @@ -0,0 +1,2 @@ +0 0.282639 0.171298 0.702613 0.123016 0.714854 0.459522 0.294879 0.507803 +1 0.315949 0.253618 0.553513 0.164618 0.582816 0.411827 0.345253 0.500827 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094441_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094441_Color.jpg new file mode 100644 index 0000000..de1561e Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094441_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094441_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094441_Color.txt new file mode 100644 index 0000000..7693340 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094441_Color.txt @@ -0,0 +1,3 @@ +0 0.281888 0.176785 0.701158 0.120741 0.715283 0.454715 0.296014 0.510759 +1 0.479766 0.170000 0.715750 0.170000 0.715750 0.424625 0.479766 0.424625 + diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094455_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094455_Color.jpg new file mode 100644 index 0000000..c5fde51 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094455_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094455_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094455_Color.txt new file mode 100644 index 0000000..2cbab79 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094455_Color.txt @@ -0,0 +1,2 @@ +0 0.282365 0.177618 0.701627 0.121575 0.715752 0.455549 0.296490 0.511592 +1 0.443906 0.168333 0.684656 0.168333 0.684656 0.423778 0.443906 0.423778 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094519_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094519_Color.jpg new file mode 100644 index 0000000..e1749d0 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094519_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094519_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094519_Color.txt new file mode 100644 index 0000000..ca11c60 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094519_Color.txt @@ -0,0 +1,2 @@ +0 0.282365 0.176785 0.701627 0.120741 0.715752 0.454715 0.296490 0.510759 +1 0.412803 0.229630 0.645321 0.152271 0.671673 0.402606 0.439156 0.479965 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094531_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094531_Color.jpg new file mode 100644 index 0000000..e36966c Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094531_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094531_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094531_Color.txt new file mode 100644 index 0000000..c3666c0 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094531_Color.txt @@ -0,0 +1,2 @@ +0 0.282834 0.174271 0.702096 0.118227 0.716221 0.452201 0.296959 0.508245 +1 0.404539 0.156370 0.640439 0.174681 0.634117 0.432116 0.398217 0.413805 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094544_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094544_Color.jpg new file mode 100644 index 0000000..a1c564f Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094544_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094544_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094544_Color.txt new file mode 100644 index 0000000..346ef8e --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094544_Color.txt @@ -0,0 +1,2 @@ +0 0.282365 0.176785 0.701627 0.120741 0.715752 0.454715 0.296490 0.510759 +1 0.375077 0.248962 0.608783 0.159891 0.637782 0.400372 0.404077 0.489442 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094551_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094551_Color.jpg new file mode 100644 index 0000000..52a9e44 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094551_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094551_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094551_Color.txt new file mode 100644 index 0000000..eb76335 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094551_Color.txt @@ -0,0 +1,2 @@ +0 0.281420 0.176785 0.700689 0.120741 0.714815 0.454715 0.295545 0.510759 +1 0.353459 0.194723 0.603042 0.175350 0.609220 0.426930 0.359638 0.446303 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094558_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094558_Color.jpg new file mode 100644 index 0000000..92a6411 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094558_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094558_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094558_Color.txt new file mode 100644 index 0000000..ff99710 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094558_Color.txt @@ -0,0 +1,2 @@ +0 0.281419 0.178452 0.700689 0.122407 0.714815 0.456395 0.295545 0.512440 +1 0.335065 0.209078 0.568178 0.179372 0.578302 0.430478 0.345190 0.460184 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094607_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094607_Color.jpg new file mode 100644 index 0000000..e914314 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094607_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094607_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094607_Color.txt new file mode 100644 index 0000000..80f8f55 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094607_Color.txt @@ -0,0 +1,2 @@ +0 0.282365 0.175938 0.701627 0.119894 0.715752 0.453882 0.296491 0.509925 +1 0.334730 0.193012 0.569811 0.201766 0.566825 0.455155 0.331744 0.446401 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094647_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094647_Color.jpg new file mode 100644 index 0000000..bcde7ec Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094647_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094647_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094647_Color.txt new file mode 100644 index 0000000..e0eb305 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094647_Color.txt @@ -0,0 +1,2 @@ +0 0.280006 0.175105 0.699275 0.119060 0.713401 0.453034 0.294131 0.509079 +1 0.349167 0.186040 0.595058 0.192907 0.592849 0.442904 0.346958 0.436037 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094656_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094656_Color.jpg new file mode 100644 index 0000000..7ed94ba Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094656_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/train/094656_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094656_Color.txt new file mode 100644 index 0000000..f8a283b --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/train/094656_Color.txt @@ -0,0 +1,2 @@ +0 0.280006 0.175105 0.699275 0.119060 0.713401 0.453034 0.294131 0.509079 +1 0.315828 0.253615 0.568866 0.167803 0.595321 0.414343 0.342282 0.500156 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/val.cache b/ailai_pc/yolo_obb_dataset/ailai_test1/val.cache new file mode 100644 index 0000000..f9f0e0d Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/val.cache differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/val/094615_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094615_Color.jpg new file mode 100644 index 0000000..8337628 Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094615_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/val/094615_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094615_Color.txt new file mode 100644 index 0000000..e000e0b --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094615_Color.txt @@ -0,0 +1,2 @@ +0 0.280951 0.174271 0.700213 0.118227 0.714338 0.452201 0.295076 0.508245 +1 0.282802 0.194126 0.538176 0.192542 0.538667 0.442582 0.283293 0.444167 diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/val/094633_Color.jpg b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094633_Color.jpg new file mode 100644 index 0000000..cc364ad Binary files /dev/null and b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094633_Color.jpg differ diff --git a/ailai_pc/yolo_obb_dataset/ailai_test1/val/094633_Color.txt b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094633_Color.txt new file mode 100644 index 0000000..168d739 --- /dev/null +++ b/ailai_pc/yolo_obb_dataset/ailai_test1/val/094633_Color.txt @@ -0,0 +1,2 @@ +0 0.282365 0.175104 0.701627 0.119061 0.715752 0.453035 0.296490 0.509078 +1 0.342378 0.187129 0.589708 0.182524 0.591215 0.438357 0.343885 0.442962 diff --git a/main/README.md b/main/README.md new file mode 100644 index 0000000..e53edcc --- /dev/null +++ b/main/README.md @@ -0,0 +1,54 @@ +# RKNN 关键点推理与偏移量计算工具 + +该工具通过使用RKNN模型对输入图像进行关键点检测,并根据检测结果计算相对于固定参考点的偏移量(单位:毫米)。此外,还提供了可视化选项来展示计算结果。 + +## 目录结构 + +├── calculate_offset.py # 主程序脚本 +├── point.rknn # RKNN 模型文件 (请确保正确路径) +└── README.md # 说明文档 + +## 配置 + +在 `calculate_offset.py` 文件顶部的配置区中,您可以修改如下参数以适应您的需求: + +- **MODEL_PATH**: RKNN 模型文件路径。 +- **OUTPUT_DIR**: 输出目录路径。 +- **FIXED_REF_POINT**: 固定参考点坐标(像素)。 +- **SCALE_X**, **SCALE_Y**: 缩放因子,用于将像素坐标转换为毫米。 +- **IMG_SIZE**: 输入图像尺寸。 + +## 安装依赖 + +请确保安装了必要的 Python 库。可以通过 pip 安装: + +```bash +pip install opencv-python numpy rknnlite +``` + +## 函数调用 + +您也可以直接调用 calculate_offset_from_image 函数,以便集成到其他项目中: +示例 1: 仅获取偏移量(不画图) +** +from calculate_offset import calculate_offset_from_image +result = calculate_offset_from_image("your_image_path.jpg", visualize=False) +if result['success']: + print(f"Offset: DeltaX={result['dx_mm']:+.2f} mm, DeltaY={result['dy_mm']:+.2f} mm") +else: + print("Error:", result['message']) +** +示例 2: 获取偏移量并保存可视化图 +** +from calculate_offset import calculate_offset_from_image +result = calculate_offset_from_image("your_image_path.jpg", visualize=True) +** + +该函数返回一个包含下列字段的字典: + + success: 成功标志(True/False) + dx_mm: 水平偏移(毫米) + dy_mm: 垂直偏移(毫米) + cx: 中心点 x 坐标(像素) + cy: 中心点 y 坐标(像素) + message: 错误信息或成功提示 diff --git a/main/calculate_diff.py b/main/calculate_diff.py new file mode 100644 index 0000000..98ff4bd --- /dev/null +++ b/main/calculate_diff.py @@ -0,0 +1,230 @@ +import cv2 +import numpy as np +import os +from rknnlite.api import RKNNLite + +# ====================== 配置区 ====================== +MODEL_PATH = "point.rknn" +OUTPUT_DIR = "./output_rknn" +os.makedirs(OUTPUT_DIR, exist_ok=True) + +# 固定参考点(像素坐标) +FIXED_REF_POINT = (535, 605) + +# mm/px 缩放因子(根据标定数据填写) +width_mm = 70.0 +width_px = 42 +SCALE_X = width_mm / float(width_px) +height_mm = 890.0 +height_px = 507 +SCALE_Y = height_mm / float(height_px) +print(f"Scale factors: SCALE_X={SCALE_X:.3f} mm/px, SCALE_Y={SCALE_Y:.3f} mm/px") + +# 输入尺寸 +IMG_SIZE = (640, 640) + + +def letterbox_resize(image, size, bg_color=114): + """保持比例缩放并填充到指定大小""" + target_w, target_h = size + h, w = image.shape[:2] + scale = min(target_w / w, target_h / h) + new_w, new_h = int(w * scale), int(h * scale) + resized = cv2.resize(image, (new_w, new_h)) + canvas = np.full((target_h, target_w, 3), bg_color, dtype=np.uint8) + dx, dy = (target_w - new_w) // 2, (target_h - new_h) // 2 + canvas[dy:dy + new_h, dx:dx + new_w] = resized + return canvas, scale, dx, dy + + +def safe_sigmoid(x): + x = np.clip(x, -50, 50) + return 1.0 / (1.0 + np.exp(-x)) + + +def parse_pose_outputs(outputs, dx=0, dy=0, scale=1.0): + """ + 解析 RKNN YOLO-Pose 关键点输出 + outputs[3]: shape (1, 4, 3, 8400) -> [kpt_id, (x,y,conf), anchor] + """ + kpt_output = np.array(outputs[3])[0] # (4, 3, 8400) + confs = kpt_output[:, 2, :] # 取每个关键点的 visible_conf + mean_conf_per_anchor = np.mean(confs, axis=0) # 每个 anchor 的平均可见性 + best_anchor_idx = np.argmax(mean_conf_per_anchor) + kpt_data = kpt_output[:, :, best_anchor_idx] # (4, 3): x, y, vis_conf + + keypoints = [] + for i in range(4): + x_img = kpt_data[i, 0] + y_img = kpt_data[i, 1] + vis_conf_raw = kpt_data[i, 2] + vis_prob = safe_sigmoid(vis_conf_raw) + + # 映射回原图坐标 + x_orig = (x_img - dx) / scale + y_orig = (y_img - dy) / scale + keypoints.append([x_orig, y_orig, vis_prob]) + + return np.array(keypoints) + + +def compute_offset(keypoints, fixed_point, scale_x, scale_y): + """ + 计算中心点相对于固定参考点的偏移量(mm) + 中心点 = P0 和 P1 的中点 + 返回: (center_x, center_y, dx_mm, dy_mm) + """ + if len(keypoints) < 2: + return None + + p1, p2 = keypoints[0], keypoints[1] + cx = (p1[0] + p2[0]) / 2.0 + cy = (p1[1] + p2[1]) / 2.0 + + dx_px = cx - fixed_point[0] + dy_px = cy - fixed_point[1] + dx_mm = dx_px * scale_x + dy_mm = dy_px * scale_y + + return cx, cy, dx_mm, dy_mm + + +def visualize_result(image, keypoints, fixed_point, offset_info, save_path): + """ + 可视化关键点、参考点、中心点、偏移箭头和文字 + """ + vis = image.copy() + colors = [(0, 0, 255), (255, 0, 0), (0, 255, 0), (255, 255, 0)] + cx, cy, dx_mm, dy_mm = offset_info + fx, fy = map(int, fixed_point) + + # 绘制关键点 + for i, (x, y, conf) in enumerate(keypoints): + if conf > 0.5: + cv2.circle(vis, (int(x), int(y)), 8, colors[i], -1) + cv2.putText(vis, f"P{i}", (int(x) + 10, int(y) - 10), + cv2.FONT_HERSHEY_SIMPLEX, 0.8, colors[i], 2) + + # 绘制中心点 + cv2.circle(vis, (int(cx), int(cy)), 12, (0, 255, 0), 3) + cv2.putText(vis, "Center", (int(cx) + 20, int(cy)), + cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 3) + + # 绘制参考点 + cv2.circle(vis, (fx, fy), 15, (255, 255, 0), 3) + cv2.putText(vis, "Ref", (fx + 20, fy), + cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 3) + + # 绘制偏移箭头和文字 + cv2.arrowedLine(vis, (fx, fy), (int(cx), int(cy)), (0, 255, 255), 3, tipLength=0.05) + cv2.putText(vis, f"DeltaX={dx_mm:+.1f}mm", (fx + 40, fy - 40), + cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 255), 3) + cv2.putText(vis, f"DeltaY={dy_mm:+.1f}mm", (fx + 40, fy + 40), + cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 255), 3) + + cv2.imwrite(save_path, vis) + + +def calculate_offset_from_image(image_path, visualize=False): + """ + 主函数:输入图片路径,输出偏移量 (dx_mm, dy_mm) + + 参数: + image_path (str): 输入图像路径 + visualize (bool): 是否保存可视化结果 + + 返回: + dict: { + 'success': bool, + 'dx_mm': float or None, + 'dy_mm': float or None, + 'cx': float or None, # 中心点 x + 'cy': float or None, # 中心点 y + 'message': str + } + """ + # 读取图像 + orig = cv2.imread(image_path) + if orig is None: + return { + 'success': False, + 'dx_mm': None, 'dy_mm': None, 'cx': None, 'cy': None, + 'message': f'Failed to load image: {image_path}' + } + + h0, w0 = orig.shape[:2] + + # 预处理 + img_resized, scale, dx, dy = letterbox_resize(orig, IMG_SIZE) + infer_img = np.expand_dims(img_resized[..., ::-1], 0).astype(np.uint8) + + # 加载模型并推理 + rknn = RKNNLite(verbose=False) + ret = rknn.load_rknn(MODEL_PATH) + if ret != 0: + return { + 'success': False, + 'dx_mm': None, 'dy_mm': None, 'cx': None, 'cy': None, + 'message': 'Failed to load RKNN model' + } + + try: + rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0) + outputs = rknn.inference([infer_img]) + except Exception as e: + rknn.release() + return { + 'success': False, + 'dx_mm': None, 'dy_mm': None, 'cx': None, 'cy': None, + 'message': f'Inference error: {str(e)}' + } + finally: + rknn.release() + + # 解析关键点 + try: + keypoints = parse_pose_outputs(outputs, dx=dx, dy=dy, scale=scale) + except Exception as e: + return { + 'success': False, + 'dx_mm': None, 'dy_mm': None, 'cx': None, 'cy': None, + 'message': f'Parse keypoint error: {str(e)}' + } + + # 计算偏移 + offset_info = compute_offset(keypoints, FIXED_REF_POINT, SCALE_X, SCALE_Y) + if offset_info is None: + return { + 'success': False, + 'dx_mm': None, 'dy_mm': None, 'cx': None, 'cy': None, + 'message': 'Not enough keypoints to compute offset' + } + + cx, cy, dx_mm, dy_mm = offset_info + + # 可视化(可选) + if visualize: + vis_save_path = os.path.join(OUTPUT_DIR, f"result_{os.path.basename(image_path)}") + visualize_result(orig, keypoints, FIXED_REF_POINT, offset_info, vis_save_path) + + return { + 'success': True, + 'dx_mm': dx_mm, + 'dy_mm': dy_mm, + 'cx': cx, + 'cy': cy, + 'message': 'Success' + } + + +# ====================== 使用示例 ====================== +if __name__ == "__main__": + image_path = "11.jpg" + + result = calculate_offset_from_image(image_path, visualize=True) + + if result['success']: + print(f"Center point: ({result['cx']:.1f}, {result['cy']:.1f})") + print(f"Offset: DeltaX={result['dx_mm']:+.2f} mm, DeltaY={result['dy_mm']:+.2f} mm") + else: + print("Error:", result['message']) \ No newline at end of file diff --git a/main/point.rknn b/main/point.rknn new file mode 100644 index 0000000..1ba05e9 Binary files /dev/null and b/main/point.rknn differ