You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何利用YOLO格式标注坐标自动批量裁剪图像中的头部区域

批量裁剪YOLO标注头部区域的解决方案

Hi Shawon,我来帮你搞定这个批量裁剪的问题!你的单张图代码思路方向是对的,但有两个关键问题需要修正:一是没实现批量文件处理逻辑,二是YOLO标注的坐标转换逻辑需要调整(YOLO给出的是中心点坐标,不是裁剪区域的左上角坐标)。下面是完整的解决方案:

先明确YOLO标注格式

YOLO的txt标注文件每行格式为:class_id x_center y_center width height,所有数值都是相对于图像宽高的归一化值(范围0-1),我们需要把这些值转换成图像上的实际像素坐标,才能正确定位裁剪区域。

修正后的批量处理代码

这个代码会自动遍历指定文件夹内的所有图像和对应标注文件,裁剪出每个标注的头部区域并保存:

import cv2
import os

# 配置你的文件夹路径
image_dir = "path/to/your/images"  # 存放原始图像的文件夹
label_dir = "path/to/your/labels"  # 存放YOLO标注txt的文件夹
output_dir = "path/to/save/cropped_heads"  # 裁剪后图像的保存路径

# 创建输出文件夹(如果不存在则自动创建)
os.makedirs(output_dir, exist_ok=True)

# 遍历所有图像文件
for filename in os.listdir(image_dir):
    # 只处理常见图像格式(可根据你的需求添加/修改后缀)
    if filename.endswith((".jpg", ".jpeg", ".png")):
        # 获取对应标注文件名(和图像同名,后缀替换为txt)
        label_filename = os.path.splitext(filename)[0] + ".txt"
        label_path = os.path.join(label_dir, label_filename)
        
        # 读取图像
        img_path = os.path.join(image_dir, filename)
        img = cv2.imread(img_path)
        if img is None:
            print(f"无法读取图像: {img_path}")
            continue
        
        dh, dw, _ = img.shape
        
        # 检查标注文件是否存在
        if not os.path.exists(label_path):
            print(f"未找到对应标注文件: {label_path}")
            continue
        
        # 读取标注内容
        with open(label_path, 'r') as f:
            lines = f.readlines()
        
        # 处理每个标注(假设所有标注都是头部,若有多个类别可通过class_id筛选)
        for idx, line in enumerate(lines):
            parts = line.strip().split()
            if len(parts) != 5:
                print(f"标注格式错误,跳过该行: {line}")
                continue
            
            # 解析标注参数
            class_id, x_center, y_center, width, height = parts
            x_center = float(x_center)
            y_center = float(y_center)
            width = float(width)
            height = float(height)
            
            # 转换为实际像素坐标:计算裁剪区域的左上角和右下角
            x1 = int((x_center - width/2) * dw)  # 左上角x坐标
            y1 = int((y_center - height/2) * dh) # 左上角y坐标
            x2 = int((x_center + width/2) * dw)  # 右下角x坐标
            y2 = int((y_center + height/2) * dh) # 右下角y坐标
            
            # 处理边界问题:确保裁剪区域不超出图像范围
            x1 = max(0, x1)
            y1 = max(0, y1)
            x2 = min(dw - 1, x2)
            y2 = min(dh - 1, y2)
            
            # 执行裁剪
            cropped_img = img[y1:y2, x1:x2]
            
            # 保存裁剪后的图像(文件名格式:原图像名_头部序号.jpg)
            save_filename = f"{os.path.splitext(filename)[0]}_head_{idx+1}.jpg"
            save_path = os.path.join(output_dir, save_filename)
            cv2.imwrite(save_path, cropped_img)
            
            print(f"已完成裁剪并保存: {save_path}")

print("所有图像批量裁剪完成!")

关键注意事项

  • 文件匹配:确保每个图像都有对应的同名txt标注文件,比如person1.jpg对应person1.txt。
  • 类别筛选:如果你的标注包含多个类别(不止头部),可以添加判断逻辑,比如if class_id == "0"(假设头部的class_id为0),只裁剪头部标注。
  • 边界防护:代码中加入了max(0, ...)和min(dw-1, ...)的判断,避免因标注坐标超出图像范围导致的裁剪错误。
  • 格式适配:如果你的图像是其他格式(如bmp),记得修改代码中的后缀判断条件。

你之前的代码直接用x*dw作为左上角x坐标,这其实是标注的中心点x值,会导致裁剪区域位置偏移,上面的代码已经修正了这个核心问题,现在应该能精准裁剪出所有图像的头部区域啦!

内容的提问来源于stack exchange,提问作者Shawon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:44:08