简化目标检测:使用 Grounding DINO 对自定义数据集进行标注

news/2024/11/29 19:59:26/

点击下方卡片,关注“小白玩转Python”公众号

对于像 YOLO 这样的模型,使用带有标注图像数据集进行训练有时可能会有点令人望而却步。如果你需要处理自定义数据,并围绕其定义标注,那可能会有些耗时。但我找到了完美的解决方案——Grounding DINO!这种方法的突破之处在于,它将基于 Transformer 的检测器 DINO 与基础预训练相结合,可以从有限的人类输入中检测到任意对象。这篇简易指南向你解释了如何有效地将你的自定义数据集格式化为 PASCAL VOC 格式,并且让你惊讶地发现,在你的目标检测项目中,这些数据集可以轻松而有效地使用。

什么是图像标注? 

对于目标检测,图像标注是训练机器学习模型以准确识别和定位图像中对象的基本步骤。这个过程包括使用边界框对感兴趣的每个对象进行标记,并提供相应的标签来描述每个对象是什么。让我们深入了解为什么这是必要的,它的用途以及其中涉及的挑战,包括为什么很难找到符合你特定需求的预标注数据。

为什么标注是必要的 

  • 机器学习模型的训练数据目标检测模型通过观察示例来学习识别定义不同对象的模式和特征。这些示例被准确地标注,模型的性能就会越好。 

  • 精确度和准确性:正确的标注确保模型不仅能够识别对象,还能在不同的背景和环境中精确定位它们。这对于需要精确对象定位的应用非常重要,比如自动驾驶和医学影像。 

  • 多样化学习:通过对来自各种场景和对象变化的图像进行标注,模型可以学习更好地泛化,并在真实世界的情况下表现良好,减少误识别的可能性。

带标注图像的用途 

  • 自动驾驶:用于安全地检测行人、其他车辆和路标,以便导航。 

  • 零售:用于识别货架上的产品,以便进行库存管理或自助结账系统。 

  • 医疗保健:通过准确定位医学扫描中感兴趣的区域来帮助诊断。 

  • 监控:用于监视区域以检测可疑活动或跟踪感兴趣的对象。 

手动标注中的挑战 

  • 耗时:在成千上万张图像中手动绘制边界框并标记每个对象是非常费时费力的。 

  • 需要准确性:边界框的准确绘制至关重要。不准确的标注会导致模型训练不良。 

  • 需要专业知识:某些领域需要具有专业知识的标注者,尤其是在医疗保健等领域,在那里理解医学图像至关重要。 

  • 可扩展性:随着数据量的增长,手动标注过程的规模化变得越来越具有挑战性,需要大量的人力资源投入。 

预先标注数据的难度 

  • 特定要求:项目通常在要检测的对象方面具有独特要求,这使得很难找到完全符合这些需求的数据集。 

  • 质量和可靠性:公共数据集的质量和标注标准可能各不相同,这可能会影响目标检测模型的性能。 

  • 覆盖范围有限:某些领域或稀有对象可能在公开可用的数据集中代表性不足。 

  • 法律和隐私问题:使用预先标注的数据集可能会受到限制,或者需要遵守隐私法律,尤其是涉及人物或敏感地点的图像。

标注格式 

图像标注存在各种格式,让我们简要了解一下其中一些:

  • PASCAL VOC 格式包含 XML 文件,详细描述图像信息、对象类标签和边界框坐标。 

  • COCO 格式包含 JSON 文件,其中包含图像元数据、类别 ID 和边界框或分割掩码的标注。

  • YOLO 格式主要用于实时目标检测,每个图像都有一个文本文件,列出每个对象的类索引和归一化的边界框坐标。 

什么是 Grounding DINO? 

Grounding DINO 是一种创新的目标检测方法,它将基于 Transformer 的检测器 DINO 的优势与基础预训练相结合,实现了开放集目标检测。这意味着它可以检测到在训练期间未见过的对象,使其成为零样本模型。让我们分解一下 Grounding DINO 的显著之处以及它如何完成图像标注。

它使用基于 PyTorch 的框架设计用于开放集目标检测,即识别和定位模型没有显式训练识别的对象的任务。它通过 DINO 的架构和一种新颖的基础预训练策略的结合来实现这一点。像 Grounding DINO 这样的零样本模型可以识别未经直接训练的对象,这要归功于它理解和处理语言描述的能力。Grounding DINO 利用语言作为连接已见和未见对象的桥梁,使其能够仅基于文本描述识别项目。这种能力对于那些不可能为每个可能遇到的对象提供训练数据的应用非常有用。

如何标注图像?

Grounding DINO 通过接受图像和文本[标签]对作为输入。然后,它输出带有所有输入词的相似度分数的对象框,从而允许根据它们的文本描述检测对象。该模型使用阈值来决定哪些框要考虑,基于最高相似度分数,并且如果它们的分数超过一定阈值,则提取预测标签的词。这种方法使 Grounding DINO 不仅能够检测对象,还能够准确理解和标记它们,从根本上自动化了标注过程。用户可以指定短语以定位图像中特定的对象,使 Grounding DINO 成为创建带标注数据集的灵活工具。

以下是使用 Grounding DINO 自动标注图像的逐步指南,针对 Google Colab 环境进行了定制。该过程将指导您设置环境、安装 Grounding DINO、下载您的数据并对图像进行标注。

开始标注

步骤 1:检查 GPU 可用性 使用 !nvidia-smi 命令来检查是否有 GPU 可用以加快处理速度。

步骤 2:挂载 Google Drive(可选) 如果您的数据存储在 Google Drive 上,请使用以下代码挂载它:

from google.colab import drive
drive.mount('/content/drive')

步骤 3:设置主目录 定义一个 HOME 常量,以便轻松管理数据集、图像和模型:

import os
HOME = os.getcwd()
print(HOME)

步骤 4:安装 Grounding DINO 克隆 Grounding DINO 存储库,切换到特定的功能分支(如果需要),并安装依赖项:

%cd {HOME}
!git clone <https://github.com/IDEA-Research/GroundingDINO.git>
%cd {HOME}/GroundingDINO# we use latest Grounding DINO model API that is not official yet
!git checkout feature/more_compact_inference_api
!pip install -q -e .
!pip install -q roboflow dataclasses-json onemetric

步骤 5:额外的依赖和验证 CUDA 和 PyTorch 确保正确安装并兼容 CUDA 和 PyTorch:

import torch
!nvcc --version
TORCH_VERSION = ".".join(torch.__version__.split(".")[:2])
CUDA_VERSION = torch.__version__.split("+")[-1]
print("torch: ", TORCH_VERSION, "; cuda: ", CUDA_VERSION)import roboflow
import supervision
print("roboflow:", roboflow.__version__,"; supervision:", supervision.__version__
)
# confirm that configuration file exist
import os
CONFIG_PATH = os.path.join(HOME, "GroundingDINO/groundingdino/config/GroundingDINO_SwinT_OGC.py")
print(CONFIG_PATH, "; exist:", os.path.isfile(CONFIG_PATH))

步骤 6:下载配置和权重 确保克隆的存储库中存在配置文件,并下载模型权重:

# download weights file
%cd {HOME}
!mkdir {HOME}/weights
%cd {HOME}/weights
!wget -q <https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth>
# confirm that weights file exist
import os
WEIGHTS_PATH = os.path.join(HOME, "weights", "groundingdino_swint_ogc.pth")
print(WEIGHTS_PATH, "; exist:", os.path.isfile(WEIGHTS_PATH))

步骤 7:下载并准备您的数据集 如果您的数据集被压缩在您的驱动器中,请将其解压缩到本地目录:

import zipfile
# Path to the zip file
zip_file_path = "/content/drive/MyDrive/....[your file path]"
# Directory to extract the contents of the zip file
extract_dir = "/content/data"
# Unzip the file
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:zip_ref.extractall(extract_dir)
print("Extraction complete.")

步骤 8:加载 Grounding DINO 模型 使用配置和权重路径加载模型:

%cd {HOME}/GroundingDINO
from groundingdino.util.inference import Model
model = Model(model_config_path=CONFIG_PATH, model_checkpoint_path=WEIGHTS_PATH)

步骤 9:对数据集进行标注并保存为 PASCAL voc 使用模型对图像进行标注。

您可以根据需要以不同的模式运行推断,如标题、类别或增强类别。推断后,使用检测结果和标签通过您喜欢的方法或提供的实用函数来标注图像。通过迭代您的图像来自动标注整个数据集,运行模型以检测对象,并保存带有标注的图像及其 PASCAL VOC XML 文件。

import os
import cv2
import xml.etree.ElementTree as ET
from groundingdino.util.inference import Model
from tqdm import tqdm# Define the home directory and the path to the dataset
HOME = "/content"
DATASET_DIR = os.path.join(HOME, "data", "ingredients_images_dataset")
# Load the Grounding DINO model
MODEL_CONFIG_PATH = os.path.join(HOME, "GroundingDINO", "groundingdino", "config", "GroundingDINO_SwinT_OGC.py")
WEIGHTS_PATH = os.path.join(HOME, "weights", "groundingdino_swint_ogc.pth")
model = Model(model_config_path=MODEL_CONFIG_PATH, model_checkpoint_path=WEIGHTS_PATH)
# Load class labels from the file
LABELS_FILE_PATH = "[ txt file path containing your images labels one per line]"
with open(LABELS_FILE_PATH, "r") as f:CLASSES = [line.strip() for line in f.readlines()]
# Define annotation thresholds
BOX_THRESHOLD = 0.35
TEXT_THRESHOLD = 0.25
# Function to enhance class names
def enhance_class_name(class_names):return [f"all {class_name}s" for class_name in class_names]
# Function to create Pascal VOC format XML annotation
def create_pascal_voc_xml(image_filename, image_shape, boxes, labels):annotation = ET.Element("annotation")folder = ET.SubElement(annotation, "folder")folder.text = "ingredient_annotations"  # Folder name for annotationsfilename = ET.SubElement(annotation, "filename")filename.text = image_filenamesource = ET.SubElement(annotation, "source")database = ET.SubElement(source, "database")database.text = "Unknown"size = ET.SubElement(annotation, "size")width = ET.SubElement(size, "width")height = ET.SubElement(size, "height")depth = ET.SubElement(size, "depth")width.text = str(image_shape[1])height.text = str(image_shape[0])depth.text = str(image_shape[2])segmented = ET.SubElement(annotation, "segmented")segmented.text = "0"for box, label in zip(boxes, labels):object = ET.SubElement(annotation, "object")name = ET.SubElement(object, "name")pose = ET.SubElement(object, "pose")truncated = ET.SubElement(object, "truncated")difficult = ET.SubElement(object, "difficult")bndbox = ET.SubElement(object, "bndbox")xmin = ET.SubElement(bndbox, "xmin")ymin = ET.SubElement(bndbox, "ymin")xmax = ET.SubElement(bndbox, "xmax")ymax = ET.SubElement(bndbox, "ymax")name.text = labelpose.text = "Unspecified"truncated.text = "0"difficult.text = "0"xmin.text = str(int(box[0]))ymin.text = str(int(box[1]))xmax.text = str(int(box[2]))ymax.text = str(int(box[3]))# Format the XML for better readabilityxml_string = ET.tostring(annotation, encoding="unicode")return xml_string
# Function to annotate images in a directory and save annotated images in Pascal VOC format
def annotate_images_in_directory(directory):for class_name in CLASSES:class_dir = os.path.join(directory, class_name)annotated_dir = os.path.join(directory, f"{class_name}_annotated")os.makedirs(annotated_dir, exist_ok=True)print("Processing images in directory:", class_dir)if os.path.isdir(class_dir):for image_name in tqdm(os.listdir(class_dir)):image_path = os.path.join(class_dir, image_name)image = cv2.imread(image_path)if image is None:print("Failed to load image:", image_path)continuedetections = model.predict_with_classes(image=image,classes=enhance_class_name([class_name]),box_threshold=BOX_THRESHOLD,text_threshold=TEXT_THRESHOLD)# Drop potential detections with phrase not part of CLASSES setdetections = detections[detections.class_id != None]# Drop potential detections with area close to area of the whole imagedetections = detections[(detections.area / (image.shape[0] * image.shape[1])) < 0.9]# Drop potential double detectionsdetections = detections.with_nms()# Create the Pascal VOC XML annotation for this imagexml_annotation = create_pascal_voc_xml(image_filename=image_name, image_shape=image.shape, boxes=detections.xyxy, labels=[class_name])# Save the Pascal VOC XML annotation to a filexml_filename = os.path.join(annotated_dir, f"{os.path.splitext(image_name)[0]}.xml")with open(xml_filename, "w") as xml_file:xml_file.write(xml_annotation)# Save the annotated imageannotated_image_path = os.path.join(annotated_dir, image_name)cv2.imwrite(annotated_image_path, image)
# Annotate images in the dataset directory
annotate_images_in_directory(DATASET_DIR)

结论

总之,Grounding DINO 彻底改变了我们处理图像标注的方式,简化了传统上既耗时又复杂的过程。本指南向您展示了如何利用 Grounding DINO 的强大功能进行高效的开放集目标检测,简化了您在人工智能和机器学习项目中的工作。使用这些技巧,您可以快速、轻松地处理自定义数据集,并让您的目标检测模型在不同场景中表现出色。

只需几个简单的步骤,您就可以为您的图像数据集生成准确的标注,并训练具有高性能的目标检测模型。无论您是在研究、开发新应用程序还是为客户提供服务,Grounding DINO 都将成为您的宝贵工具。

·  END  ·

HAPPY LIFE

1702558895353c273b1fa3f048e7380a.png

本文仅供学习交流使用,如有侵权请联系作者删除


http://www.ppmy.cn/news/1431223.html

相关文章

k8s pod 绑核

一、概述 默认配置下&#xff0c;kubelet/Linux 使用 CFS&#xff08;完全公平调度&#xff09;算法来为 Pod 分配 CPU&#xff0c;工作负载&#xff08;Pod 中的进程&#xff09;会被调度到不同的可用的 CPU 核心&#xff0c;而且大多数工作负载对这种迁移带来的性能损失并不…

个人网站的SEO优化系列——如何实现搜索引擎的收录

如果你自己做了一个网站&#xff0c;并且想让更多的人知道你的网站&#xff0c;那么无非就是两种途径 一、自己进行宣传&#xff0c;或者花钱宣传 二、使用搜索引擎的自然流量 而如果搜索引擎都没有收录你的站点&#xff0c;别说是自然流量&#xff0c;就算是使用特定语句【sit…

支持三十多个算法的免费科学计算API

科学计算API支持的算法规则&#xff0c;在使用接口时请注意&#xff0c;num参数应该传一个数字&#xff08;整数、浮点数&#xff09;或两个数字&#xff0c;并以“,”半角逗号分隔。在计算时&#xff0c;第一和第二个&#xff08;逗号左右两侧&#xff09;数字相互计算。在百分…

A Neural Span-Based Continual Named Entity Recognition Model

《A Neural Span-Based Continual Named Entity Recognition Model》------------AAAI’23 论文链接&#xff1a;https://arxiv.org/abs/2302.12200 代码&#xff1a;https://github.com/Qznan/SpanKL 当前问题&#xff1a; 1.现有的NER模型在适应新的实体类型时往往表现不佳…

orbslam2+kitti数据集序列图像

文章目录 一、下载ORB Slam2依赖二、安装编译ORB_SLAM2三 、运行Kitee数据集3.1 数据集准备3.2 启动&#xff01;&#xff01;&#xff01; 安装ORB Slam2遇到的问题总结参考资料 一、下载ORB Slam2依赖 Orb Slam2 需要下载的依赖项&#xff1a; Pangolin0.5 、Eigen3.1以上、…

SQL的基础语句

1、select语句 select colums from table_name 2、条件语句 #查询出查询出用户id为1和3的用户记录 IN 操作符允许我们在 WHERE 子句中规定多个值。 select * from student where id in (1,3) #查询出所有姓王的同学 模糊查询 like 通配符(% 任意多个字符 _单个字符) #下例…

ubuntu系统安装配置gitlab+Jenkins+发布持续集成持续部署保姆级教程。

1、服务器环境 名称 系统 IP 备注 gitlab ubuntu20.04.2图形化 192.168.26.130 要求有6G的内存 Jenkins Ubuntu20.04.2图形化 …

asp.net get请求base64解密报错问题

刚开始没编码&#xff0c;使用encodeURIComponent进行了编码&#xff0c;但是后台解码会被解析为空格&#xff0c;最后使用hex解决 public class HexConverter {/// <summary>/// 转换十六进制字符串到字节数组/// </summary>/// <param name"msg"&g…