当前位置: 首页 > news >正文

BYU-YOLO数据格式准备

BYU - Locating Bacterial Flagellar Motors 2025(在3D断层扫描图像中定位细菌鞭毛马达)

一、数据介绍

1.竞赛介绍

在本次竞赛中,您的任务是在3D断层扫描图像中找到鞭毛马达的中心位置。断层扫描图像是物体的三维体积表示。每个断层扫描图像作为一个独立的目录提供,其中包含一系列2D图像切片(JPEG格式)。您需要预测存在鞭毛马达时其在三维空间中的位置点。

2.文件和目录说明

  • train/:包含多个子目录,每个子目录对应一个用于训练的断层扫描图像。每个断层扫描子目录包含多个JPEG文件,每个JPEG文件是该断层扫描图像的一个2D切片。

  • train_labels.csv:训练数据标签。每一行代表一个唯一的马达位置,而不是一个唯一的断层扫描图像。列包括:

    • row_id:行索引
    • tomo_id:断层扫描图像的唯一标识符。某些断层扫描图像包含多个马达。
    • Motor axis 0:马达的z坐标,即所在的切片编号
    • Motor axis 1:马达的y坐标
    • Motor axis 2:马达的x坐标
    • Array shape axis 0:z轴长度,即断层扫描图像的切片数量
    • Array shape axis 1:y轴长度,即每个切片的高度
    • Array shape axis 2:x轴长度,即每个切片的宽度
    • Voxel spacing:体素间距,即每个体素的埃(Å)数
    • Number of motors:断层扫描图像中的马达数量。注意,每一行代表一个马达,因此包含多个马达的断层扫描图像将有多个行来定位每个马达。
  • test/:包含三个测试断层扫描图像的目录;重新运行的测试数据集包含大约900个断层扫描图像。测试数据仅包含具有一个或零个马达的断层扫描图像。

  • sample_submission.csv:正确格式的示例提交文件。(如果您预测某个断层扫描图像中不存在马达,请将Motor axis 0Motor axis 1Motor axis 2设置为-1)。

3.提交格式

提交文件应遵循sample_submission.csv文件的格式。对于每个断层扫描图像,您需要预测:

  • Motor axis 0(z坐标)
  • Motor axis 1(y坐标)
  • Motor axis 2(x坐标)

如果断层扫描图像中未检测到马达,请将所有三个坐标设置为-1

二、YOLO数据准备

在目标检测任务中,准备高质量的训练数据是模型成功的关键。本文将详细讲解一段用于准备 YOLO(You Only Look Once)目标检测模型训练数据的 Python 脚本。该脚本从 3D 断层扫描图像(tomograms)中提取包含电机(motors)的切片,并将其转换为 YOLO 数据集格式。

代码详解

1. 导入模块

import os
import numpy as np
import pandas as pd
from PIL import Image
import shutil
import time
import yaml
from pathlib import Path
from tqdm.notebook import tqdm  # Use tqdm.notebook for Jupyter/Kaggle environments
import concurrent.futures  # 导入多线程模块
  • os:用于文件和目录操作。
  • numpy (np):用于数值计算和数组操作。
  • pandas (pd):用于数据处理和分析。
  • PIL.Image:用于图像处理。
  • shutil:用于文件复制和移动。
  • time:用于时间相关操作。
  • yaml:用于读写 YAML 格式文件。
  • Path:用于路径操作。
  • tqdm.notebook:用于在 Jupyter Notebook 或 Kaggle 环境中显示进度条。
  • concurrent.futures:用于实现多线程处理。

2. 设置随机种子

np.random.seed(42)

设置随机种子为 42,确保每次运行代码时随机操作的结果是可重复的。

3. 定义路径

data_path = "/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/"
train_dir = os.path.join(data_path, "train")

yolo_dataset_dir = "/kaggle/working/yolo_dataset"
yolo_images_train = os.path.join(yolo_dataset_dir, "images", "train")
yolo_images_val = os.path.join(yolo_dataset_dir, "images", "val")
yolo_labels_train = os.path.join(yolo_dataset_dir, "labels", "train")
yolo_labels_val = os.path.join(yolo_dataset_dir, "labels", "val")
  • data_path:原始数据集的路径。
  • train_dir:包含训练数据的目录。
  • yolo_dataset_dir:YOLO 数据集的根目录。
  • yolo_images_trainyolo_images_val:分别是训练集和验证集的图像目录。
  • yolo_labels_trainyolo_labels_val:分别是训练集和验证集的标注目录。

4. 创建目录

for dir_path in [yolo_images_train, yolo_images_val, yolo_labels_train, yolo_labels_val]:
    os.makedirs(dir_path, exist_ok=True)

创建 YOLO 数据集所需的目录结构,如果目录已存在,则不会重复创建。

5. 定义常量

TRUST = 4  # 定义了在中心切片上下各取多少切片。具体来说,它决定了从中心切片(z_center)向上和向下各扩展多少个切片,总共处理的切片数量为 2 * TRUST + 1
BOX_SIZE = 24  # 标注框的大小(以像素为单位)。这个值用于确定每个电机在图像中的标注框的宽度和高度。
TRAIN_SPLIT = 0.8  # 80% for training, 20% for validation
  • TRUST:定义了在中心切片上下各取多少切片(总共 2 * TRUST + 1 个切片)。
  • BOX_SIZE:定义了标注框的大小(以像素为单位)。
  • TRAIN_SPLIT:定义了训练集和验证集的划分比例(80% 用于训练,20% 用于验证)。

在代码中,BOX_SIZE 是一个非常重要的常量,它定义了标注框(bounding box)的大小,用于目标检测任务。具体来说,BOX_SIZE 的作用如下:

5.1. 标注框的大小

在目标检测任务中,每个目标(例如电机)的位置通常用一个矩形框(标注框)来表示。BOX_SIZE 定义了这个矩形框的宽度和高度(假设标注框是正方形)。例如,如果 BOX_SIZE = 24,则标注框的宽度和高度均为 24 个像素。

5.2. 在代码中的具体应用

在代码的 process_motor 函数中,BOX_SIZE 被用于计算标注框的归一化坐标。以下是相关代码片段:

box_width_norm = BOX_SIZE / img_width
box_height_norm = BOX_SIZE / img_height
  • img_widthimg_height 分别是图像的宽度和高度。
  • box_width_normbox_height_norm 是标注框的宽度和高度归一化到 [0, 1] 范围内的值。
  • 这些归一化后的值是 YOLO 模型所需的标注格式。
5.3. YOLO 标注格式

YOLO 模型的标注文件格式要求标注框的中心点坐标和宽度、高度都归一化到 [0, 1] 范围内。标注文件的每一行表示一个目标,格式如下:

<class> <x_center> <y_center> <width> <height>
  • <class> 是目标的类别(在本例中为 0,表示电机)。
  • <x_center><y_center> 是标注框中心点的归一化坐标。
  • <width><height> 是标注框的归一化宽度和高度。

BOX_SIZE 的值直接影响标注框的大小,从而决定了模型在训练和推理时对目标的检测范围。例如,如果 BOX_SIZE 设置得过大,标注框可能会覆盖多个目标;如果设置得过小,可能会无法完全覆盖目标。

6. 图像归一化函数

def normalize_slice(slice_data):
    """
    Normalize slice data using 2nd and 98th percentiles
    """
    p2 = np.percentile(slice_data, 2)
    p98 = np.percentile(slice_data, 98)
    clipped_data = np.clip(slice_data, p2, p98)
    normalized = 255 * (clipped_data - p2) / (p98 - p2)
    return np.uint8(normalized)

使用 2% 和 98% 的百分位数对图像数据进行裁剪,以去除异常值。将裁剪后的数据归一化到 [0, 255] 范围内,并转换为 8 位无符号整数。

7. 处理单个电机的函数

def process_motor(tomo_id, z_center, y_center, x_center, z_max, images_dir, labels_dir, trust=TRUST):
    """
    Process a single motor and save the slices and labels
    """
    """这两个变量定义了以 z_center 为中心,向上和向下扩展 trust 个切片的范围。这样可以确保在处理电机时,不仅包括中心切片,还包括其周围的切片,从而捕捉到更多的上下文信息,有助于提高模型的检测准确性。"""
    z_min = max(0, z_center - trust) # 确保了在 z 轴上不会低于 0
    z_max = min(z_max - 1, z_center + trust) # 确保了在 z 轴上不会超过断层扫描图像的最大切片数减一
    processed_slices = 0
    for z in range(z_min, z_max + 1):
        slice_filename = f"slice_{
     z:04d}.jpg" # 根据当前切片编号 z 生成一个格式化的文件名,确保文件名是 4 位数字,不足 4 位时用前导零填充。
        src_path = os.path.join(train_dir, tomo_id, slice_filename) # 加载图片
        if not os.path.exists(src_path):
            print(f"Warning: {
     src_path} does not exist, skipping.")
            continue
        img = Image.open(src_path)
        img_array = np.array(img)
        normalized_img = normalize_slice(img_array) # 归一化处理图片
        dest_filename = f"{
     tomo_id}_z{
     z:04d}_y{
     y_center:04d}_x{
     x_center:04d}.jpg" # 保存的图片
        dest_path = os.path.join(images_dir, dest_filename) # 保存图像的地址
        Image.fromarray(normalized_img).save(dest_path)
        """这里是yolo数据格式的计算方法,这里做了归一化处理"""
        img_width, img_height = img.size
        x_center_norm = x_center / img_width
        y_center_norm = y_center / img_height
        box_width_norm = BOX_SIZE / img_width
        box_height_norm = BOX_SIZE / img_height
        label_path = os.path.join(labels_dir, dest_filename.replace('.jpg', '.txt'))
        with open(label_path, 'w') as f:
            f.write(f"0 {
     x_center_norm} {
     y_center_norm} {
     box_width_norm} {
     box_height_norm}\n")
        processed_slices += 1
    return processed_slices

YOLO 格式的标注文件要求标注框的中心坐标和尺寸都归一化到 [0, 1] 范围内。这样做的好处是:
模型鲁棒性:归一化使得模型对不同尺寸的输入图像具有更好的鲁棒性。<

相关文章:

  • 群体智能优化算法-灰狼优化算法(Grey Wolf Optimizer, GWO,含Matlab源代码)
  • 【时时三省】(C语言基础)习题:分析一个程序
  • 深入理解traceroute命令及其原理
  • 药房链路轨道“空间拓扑优化+动态算法决策+多级容错控制”三重链式编程技术解析与应用
  • 大模型应用中如何保持实时性和多人对话一致性问题?
  • 蓝桥杯练习day2:拿硬币
  • Linux日志管理
  • 微分方程求解及推导过程
  • 华为欧拉 22.03 版本部署 nginx
  • 【AIGC前沿】MiniMax海螺AI视频——图片/文本生成高质量视频
  • NET6 WebApi第5讲:中间件(源码理解,俄罗斯套娃怎么来的?);Web 服务器 (Nginx / IIS / Kestrel)、WSL、SSL/TSL
  • string练习题
  • 并发编程面试题三
  • MCP技术将重塑 SaaS 与 AI 的协作范式
  • 【操作系统】进程间通信方式
  • Boost C++ `split()` 全面解析:高效字符串拆分与优化实践
  • Spring Boot 3 新特性实战:从理论到实践
  • 15-双链表-双链表基本操作
  • 毕业论文答辩自述模板(本科、硕博均可使用)
  • Claude:从安全优先的 AI 实验室到创作者协作者(2025 深度解析)
  • 特朗普再提“接管”加沙,要将其变为“自由区”
  • 选址江南制造总局旧址,上海工业博物馆建设有新进展
  • 中国人民银行等四部门联合召开科技金融工作交流推进会
  • 远洋集团:今年前4个月销售80.9亿元,同比增加13.62%
  • 特朗普促卡塔尔说服伊朗放弃核计划,伊朗总统:你来吓唬我们?
  • 娃哈哈:自4月起已终止与今麦郎的委托代工关系,未来将坚持自有生产模式