欢迎光临
我们一直在努力

目标检测:入门篇

目标检测 

1. 什么是目标检测?

1.1.定义

目标检测是计算机视觉任务,旨在图像或视频中定位和识别感兴趣的目标。定位指找到目标的位置(如用边界框表示),识别指确定目标的类别。

  • 其关键要素:
    • 定位:用边界框(如矩形框)表示位置,坐标包括左上角$(x_{\\text{min}}, y_{\\text{min}})$  和右下角 $(x_{\\text{max}}, y_{\\text{max}})$  
    • 识别:分类目标内容,目标可以是常规物体(如人、车)或抽象概念。
    • 任务目标:根据应用需求定义感兴趣目标。

2. 目标检测常见数据集

数据集包括输入(图片)和输出(标注),评估标准包括数据量、场景覆盖度和标注质量。

  • 主要数据集介绍:
    • VOC数据集:
      • 结构:包含 Annotations(XML标注文件)和 JPEGImages(图片文件夹)。
      • 标注格式:重点关注 object 标签,包括 name(类别)和 bndbox(边界框坐标)。
      • 坐标系:图像坐标系原点在左上角,x轴向右,y轴向下。
    • COCO数据集:
      • 结构:使用 JSON 文件存储标注。
      • 标注格式:bbox 字段表示$(x_{\\text{min}}, y_{\\text{min}})$, (\\text{width}, \\text{height})
    • YOLO标注格式:
      • 结构:TXT 文件存储标注。
      • 标注格式:每行表示一个目标,格式为 class_id center_x center_y width height,其中坐标归一化到 [0,1]。

这些数据集各有其特点,VOC、COCO和YOLO格式都是计算机视觉领域常用的数据集标注格式。其中VOC格式采用XML文件存储标注信息,结构清晰且支持多任务标注,但文件体积较大且解析效率较低,适合小规模研究项目或需要详细标注的场景。COCO格式使用JSON文件组织数据,支持丰富的标注类型和层次化结构,兼容性强且被多数现代框架支持,但文件解析复杂度较高,适用于中大规模数据集和需要复杂标注的任务。YOLO格式以纯文本存储标注,每行对应一个目标的归一化坐标和类别,文件紧凑且加载高效,但缺乏元信息和多任务支持,适合实时性要求高的目标检测任务(如YOLO系列模型)。选择时需权衡标注需求、数据规模及模型兼容性——VOC适合精细化标注,COCO适合多任务研究,YOLO格式则侧重轻量化和检测效率。

3. 目标检测数据集代码实战

  • 环境配置:
    • 安装 Python、Anaconda(可选)、PyCharm 和深度学习库(如 PyTorch、OpenCV)。
    • 设置虚拟环境,确保依赖兼容。
  • 加载VOC数据集: import os
    import xml.etree.ElementTree as ET
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    from typing import List, Dict, Tuple

    class VOCDatasetLoader:
    \”\”\”VOC数据集加载器,用于加载和解析VOC格式的数据集\”\”\”

    def __init__(self, voc_root: str, split: str = \’train\’):
    \”\”\”
    初始化VOC数据集加载器

    Args:
    voc_root: VOC数据集根目录,如 \’./VOCdevkit/VOC2007\’
    split: 数据集划分,可选 \’train\’, \’val\’, \’trainval\’, \’test\’
    \”\”\”
    self.voc_root = voc_root
    self.split = split

    # 定义VOC数据集的标准路径
    self.annotations_dir = os.path.join(voc_root, \’Annotations\’)
    self.images_dir = os.path.join(voc_root, \’JPEGImages\’)
    self.image_sets_dir = os.path.join(voc_root, \’ImageSets\’, \’Main\’)

    # 获取指定划分的图片ID列表
    self.image_ids = self._get_image_ids()

    # VOC数据集的20个类别(PASCAL VOC 2007/2012)
    self.class_names = [
    \’aeroplane\’, \’bicycle\’, \’bird\’, \’boat\’, \’bottle\’,
    \’bus\’, \’car\’, \’cat\’, \’chair\’, \’cow\’,
    \’diningtable\’, \’dog\’, \’horse\’, \’motorbike\’, \’person\’,
    \’pottedplant\’, \’sheep\’, \’sofa\’, \’train\’, \’tvmonitor\’
    ]
    self.class2id = {name: idx for idx, name in enumerate(self.class_names)}

    def _get_image_ids(self) -> List[str]:
    \”\”\”获取指定划分的图片ID列表\”\”\”
    split_file = os.path.join(self.image_sets_dir, f\'{self.split}.txt\’)

    if not os.path.exists(split_file):
    raise FileNotFoundError(f\”划分文件不存在: {split_file}\”)

    with open(split_file, \’r\’) as f:
    image_ids = [line.strip() for line in f if line.strip()]

    return image_ids

    def parse_annotation(self, image_id: str) -> Dict:
    \”\”\”
    解析单个图片的标注文件

    Args:
    image_id: 图片ID(不含扩展名)

    Returns:
    包含标注信息的字典
    \”\”\”
    xml_path = os.path.join(self.annotations_dir, f\'{image_id}.xml\’)

    if not os.path.exists(xml_path):
    raise FileNotFoundError(f\”标注文件不存在: {xml_path}\”)

    tree = ET.parse(xml_path)
    root = tree.getroot()

    # 初始化标注信息
    annotation = {
    \’image_path\’: os.path.join(self.images_dir, f\'{image_id}.jpg\’),
    \’width\’: int(root.find(\’size/width\’).text),
    \’height\’: int(root.find(\’size/height\’).text),
    \’depth\’: int(root.find(\’size/depth\’).text),
    \’objects\’: []
    }

    # 解析每个目标对象
    for obj in root.findall(\’object\’):
    obj_info = {
    \’name\’: obj.find(\’name\’).text,
    \’class_id\’: self.class2id[obj.find(\’name\’).text],
    \’difficult\’: int(obj.find(\’difficult\’).text),
    \’bndbox\’: {
    \’xmin\’: int(obj.find(\’bndbox/xmin\’).text),
    \’ymin\’: int(obj.find(\’bndbox/ymin\’).text),
    \’xmax\’: int(obj.find(\’bndbox/xmax\’).text),
    \’ymax\’: int(obj.find(\’bndbox/ymax\’).text)
    }
    }
    annotation[\’objects\’].append(obj_info)

    return annotation

    def load_image(self, image_id: str) -> Tuple[cv2.Mat, Dict]:
    \”\”\”
    加载单个图片及其标注信息

    Args:
    image_id: 图片ID

    Returns:
    (图片数组, 标注信息字典)
    \”\”\”
    annotation = self.parse_annotation(image_id)
    image = cv2.imread(annotation[\’image_path\’])
    # 转换为RGB格式(OpenCV默认是BGR)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

    return image, annotation

    def __len__(self) -> int:
    \”\”\”返回数据集大小\”\”\”
    return len(self.image_ids)

    def __getitem__(self, idx: int) -> Tuple[cv2.Mat, Dict]:
    \”\”\”通过索引获取数据\”\”\”
    if idx < 0 or idx >= len(self.image_ids):
    raise IndexError(\”索引超出范围\”)

    image_id = self.image_ids[idx]
    return self.load_image(image_id)

    def visualize_sample(self, idx: int):
    \”\”\”可视化单个样本\”\”\”
    image, annotation = self[idx]

    # 创建绘图对象
    fig, ax = plt.subplots(1, figsize=(10, 8))
    ax.imshow(image)

    # 绘制每个目标的边界框
    for obj in annotation[\’objects\’]:
    bbox = obj[\’bndbox\’]
    # 创建矩形框
    rect = patches.Rectangle(
    (bbox[\’xmin\’], bbox[\’ymin\’]),
    bbox[\’xmax\’] – bbox[\’xmin\’],
    bbox[\’ymax\’] – bbox[\’ymin\’],
    linewidth=2,
    edgecolor=\’red\’,
    facecolor=\’none\’
    )
    ax.add_patch(rect)
    # 添加类

赞(0)
未经允许不得转载:171主机测评 » 目标检测:入门篇
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址