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

YOLOv8 × VisDrone 全流程实战:训练你的无人机识别模型 AI(第一部分:数据集准备)

目录

数据集处理和准备

 第一步:安装YOLOv8 Ultralytics 库

第二步:挂载你的Google Drive

第三步:解压你上传到 Google Drive 的 VisDrone 数据集

第四步:上传转换脚本和配置文件

dataset.yaml

第五步:创建 YOLO 格式所需目录结构

第六步:将解压后的图像放入YOLO工作目录

第七步:将原始数据集的标注转换为YOLO的格式

训练集

验证集

 第八步:试看其中一张观察是否有标注的数据

训练集查看

​编辑

验证集查看

​编辑

可选最后一步:标签验证


想打造属于自己的无人机目标识别AI?这篇手把手教程带你从零开始上手实战!

在本篇文章中,我们将带你完整走完 YOLOv8 与 VisDrone 数据集的整合流程,涵盖从数据获取到预处理的每一个关键步骤。无论你是初学者还是有一定基础的开发者,都能轻松跟随操作,完成无人机图像数据的标准化转换。

🔧 你将学到:

  • 如何从 GitHub 下载 VisDrone 数据集并高效管理至 Google Drive
  • 在 Google Colab 中快速部署 YOLOv8 环境并挂载云端存储
  • 解压数据并构建符合 YOLO 格式的标准目录结构
  • 将原始标注文件一键转换为 YOLO 可训练格式
  • 编写可视化函数,直观检查标注质量
  • 使用标签验证脚本确保数据完整性,避免训练翻车

✨ 完成本文操作后,你的数据将完全准备好,随时进入模型训练阶段!下一篇文章我们将正式开始 YOLOv8 的训练之旅,记得关注更新!

📌 一站式全流程教学,专为想要掌握无人机视觉识别技术的你而准备!

数据集处理和准备

        首先在这里下载好对应的数据集,分别是下载这两个。

GitHub - VisDrone/VisDrone-Dataset: The dataset for drone based detection and tracking is released, including both image/video, and annotations.

        这里我们采用保存到GoogleDrive的方法,这样的话配合GoogleColab都在云端网速不是一般的快。

        然后我们进入colab 

 第一步:安装YOLOv8 Ultralytics 库

# ✅ 安装 YOLOv8 Ultralytics 库
!pip install ultralytics

第二步:挂载你的Google Drive

# ✅ 挂载你的 Google Drive
from google.colab import drive
drive.mount('/content/drive')

第三步:解压你上传到 Google Drive 的 VisDrone 数据集

        这里是怎么放到Drive中的呢,我给的GitHub中有放入Google Drive中的链接,点击就完事了。

# ✅ 解压你上传到 Google Drive 的 VisDrone 数据集
# 替换成你自己的路径,比如你放在 "MyDrive/datasets" 里
!unzip -q "/content/drive/MyDrive/VisDrone2019-DET-train.zip" -d ./data/
!unzip -q "/content/drive/MyDrive/VisDrone2019-DET-val.zip" -d ./data/

第四步:上传转换脚本和配置文件


# ✅ 上传转换脚本和配置文件(你也可以从本地上传)
from google.colab import filesuploaded = files.upload()

dataset.yaml


path: /content/data/VisDrone-YOLO
train: images/train
val: images/valnames:0: pedestrian1: people2: bicycle3: car4: van5: truck6: tricycle7: awning-tricycle8: bus9: motor

第五步:创建 YOLO 格式所需目录结构


# ✅ 创建 YOLO 格式所需目录结构
import osbase_path = '/content/data/VisDrone-YOLO'os.makedirs(f'{base_path}/images/train', exist_ok=True)
os.makedirs(f'{base_path}/images/val', exist_ok=True)
os.makedirs(f'{base_path}/labels/train', exist_ok=True)
os.makedirs(f'{base_path}/labels/val', exist_ok=True)

第六步:将解压后的图像放入YOLO工作目录

# 复制训练集图像
!mkdir -p /content/data/VisDrone-YOLO/images/train
!cp /content/data/VisDrone2019-DET-train/images/* /content/data/VisDrone-YOLO/images/train/# 复制验证集图像
!mkdir -p /content/data/VisDrone-YOLO/images/val
!cp /content/data/VisDrone2019-DET-val/images/* /content/data/VisDrone-YOLO/images/val/

第七步:将原始数据集的标注转换为YOLO的格式

训练集

# 转换数据标注标签import os
import cv2train_image_dir = "/content/data/VisDrone-YOLO/images/train"
train_label_dir = "/content/data/VisDrone-YOLO/labels/train"
annotation_dir = "/content/data/VisDrone2019-DET-train/annotations"os.makedirs(train_label_dir, exist_ok=True)image_names = os.listdir(train_image_dir)
print(f"共{len(image_names)}张训练图片")for img_name in image_names:base_name = os.path.splitext(img_name)[0]ann_path = os.path.join(annotation_dir, base_name + ".txt")img_path = os.path.join(train_image_dir, img_name)if not os.path.exists(ann_path):print(f"警告:没有找到标注文件:{ann_path}")continueimg = cv2.imread(img_path)if img is None:print(f"错误:无法读取图片 {img_path}")continueh, w, _ = img.shapewith open(ann_path, "r") as f:lines = f.readlines()if len(lines) == 0:print(f"标注文件为空:{ann_path}")continueyolo_lines = []for line in lines:parts = line.strip().split(",")if len(parts) < 6:print(f"异常标注行(字段数小于6):{line.strip()}")continue# VisDrone标注格式:x,y,w,h,score,class,idx, y_, bw, bh, score, cls = parts[:6]x, y_, bw, bh = map(float, (x, y_, bw, bh))cls = int(cls)# 跳过部分类别?视需求而定# 归一化坐标cx = (x + bw/2) / wcy = (y_ + bh/2) / hnw = bw / wnh = bh / h# YOLO类别映射,可根据需求调整# 假设VisDrone原始类别就是0起始的yolo_lines.append(f"{cls} {cx} {cy} {nw} {nh}")if len(yolo_lines) == 0:print(f"没有有效标注转换:{ann_path}")continuesave_path = os.path.join(train_label_dir, base_name + ".txt")with open(save_path, "w") as f:f.write("\n".join(yolo_lines))# print(f"成功转换:{save_path}")

验证集

#验证集
val_image_dir = "/content/data/VisDrone-YOLO/images/val"
val_label_dir = "/content/data/VisDrone-YOLO/labels/val"
val_annotation_dir = "/content/data/VisDrone2019-DET-val/annotations"os.makedirs(val_label_dir, exist_ok=True)val_image_names = os.listdir(val_image_dir)
print(f"共{len(val_image_names)}张验证图片")for img_name in val_image_names:base_name = os.path.splitext(img_name)[0]ann_path = os.path.join(val_annotation_dir, base_name + ".txt")img_path = os.path.join(val_image_dir, img_name)if not os.path.exists(ann_path):print(f"警告:没有找到标注文件:{ann_path}")continueimg = cv2.imread(img_path)if img is None:print(f"错误:无法读取图片 {img_path}")continueh, w, _ = img.shapewith open(ann_path, "r") as f:lines = f.readlines()if len(lines) == 0:print(f"标注文件为空:{ann_path}")continueyolo_lines = []for line in lines:parts = line.strip().split(",")if len(parts) < 6:print(f"异常标注行(字段数小于6):{line.strip()}")continuex, y_, bw, bh, score, cls = parts[:6]x, y_, bw, bh = map(float, (x, y_, bw, bh))cls = int(cls)cx = (x + bw/2) / wcy = (y_ + bh/2) / hnw = bw / wnh = bh / hyolo_lines.append(f"{cls} {cx} {cy} {nw} {nh}")if len(yolo_lines) == 0:print(f"没有有效标注转换:{ann_path}")continuesave_path = os.path.join(val_label_dir, base_name + ".txt")with open(save_path, "w") as f:f.write("\n".join(yolo_lines))# print(f"成功转换:{save_path}")

 第八步:试看其中一张观察是否有标注的数据

训练集查看

import matplotlib.pyplot as plt
import cv2
import osdef plot_image_with_bbox(image_path, label_path):img = cv2.imread(image_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)h, w, _ = img.shapewith open(label_path, 'r') as f:for line in f.readlines():cls, cx, cy, bw, bh = line.strip().split()cls, cx, cy, bw, bh = int(cls), float(cx), float(cy), float(bw), float(bh)x1 = int((cx - bw/2)*w)y1 = int((cy - bh/2)*h)x2 = int((cx + bw/2)*w)y2 = int((cy + bh/2)*h)cv2.rectangle(img, (x1,y1), (x2,y2), (255,0,0), 2)cv2.putText(img, str(cls), (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255,0,0), 2)plt.imshow(img)plt.axis('off')plt.show()# 试试看其中一张
img_fp = '/content/data/VisDrone-YOLO/images/train/0000002_00005_d_0000014.jpg'  # 改成你有的图片文件名
label_fp = '/content/data/VisDrone-YOLO/labels/train/0000002_00005_d_0000014.txt'  # 同名txt
plot_image_with_bbox(img_fp, label_fp)

验证集查看

import matplotlib.pyplot as plt
import cv2
import osdef plot_image_with_bbox(image_path, label_path):img = cv2.imread(image_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)h, w, _ = img.shapewith open(label_path, 'r') as f:for line in f.readlines():cls, cx, cy, bw, bh = line.strip().split()cls, cx, cy, bw, bh = int(cls), float(cx), float(cy), float(bw), float(bh)x1 = int((cx - bw/2)*w)y1 = int((cy - bh/2)*h)x2 = int((cx + bw/2)*w)y2 = int((cy + bh/2)*h)cv2.rectangle(img, (x1,y1), (x2,y2), (255,0,0), 2)cv2.putText(img, str(cls), (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255,0,0), 2)plt.imshow(img)plt.axis('off')plt.show()# 试试看其中一张
#img_fp = '/content/data/VisDrone-YOLO/images/train/0000002_00005_d_0000014.jpg'  # 改成你有的图片文件名
#label_fp = '/content/data/VisDrone-YOLO/labels/train/0000002_00005_d_0000014.txt'  # 同名txtimg_fp = '/content/data/VisDrone-YOLO/images/val/0000001_02999_d_0000005.jpg'  # 改成你有的图片文件名
label_fp = '/content/data/VisDrone-YOLO/labels/val/0000001_02999_d_0000005.txt'  # 同名txt
plot_image_with_bbox(img_fp, label_fp)

可选最后一步:标签验证

import osdef check_labels(label_dir, image_dir, num_classes=12):label_files = [f for f in os.listdir(label_dir) if f.endswith('.txt')]image_files = set(os.listdir(image_dir))class_counts = [0] * num_classeserrors = []empty_files = []missing_images = []missing_labels = []for label_file in label_files:label_path = os.path.join(label_dir, label_file)base_name = os.path.splitext(label_file)[0]image_name_jpg = base_name + ".jpg"image_name_png = base_name + ".png"# 判断图片是否存在(支持jpg或png)if image_name_jpg not in image_files and image_name_png not in image_files:missing_images.append(base_name)with open(label_path, 'r') as f:lines = f.readlines()if len(lines) == 0:empty_files.append(label_file)continuefor i, line in enumerate(lines):parts = line.strip().split()if len(parts) < 5:errors.append(f"{label_file} line {i+1}: 字段数不足")continuetry:cls_id = int(parts[0])if cls_id < 0 or cls_id >= num_classes:errors.append(f"{label_file} line {i+1}: 类别ID {cls_id} 越界")else:class_counts[cls_id] += 1except ValueError:errors.append(f"{label_file} line {i+1}: 类别ID非整数")# 检查图片目录是否有未对应标签文件label_basenames = set(os.path.splitext(f)[0] for f in label_files)for img_file in image_files:base_name = os.path.splitext(img_file)[0]if base_name not in label_basenames:missing_labels.append(img_file)# 输出统计结果print("== 类别统计 ==")for i, count in enumerate(class_counts):print(f"类别 {i}: {count} 个标签")print(f"\n== 错误统计 ==")print(f"标签文件为空: {len(empty_files)} 个")print(f"标签格式错误或类别越界: {len(errors)} 条")print(f"缺少对应图片的标签文件数: {len(missing_images)}")print(f"缺少对应标签文件的图片数: {len(missing_labels)}")if errors:print("\n具体错误示例(最多5条):")for e in errors[:5]:print(" ", e)if empty_files:print("\n空标签文件示例(最多5个):")for f in empty_files[:5]:print(" ", f)if missing_images:print("\n缺少图片示例(最多5个):")for f in missing_images[:5]:print(" ", f)if missing_labels:print("\n缺少标签示例(最多5个):")for f in missing_labels[:5]:print(" ", f)if __name__ == "__main__":train_label_dir = "/content/data/VisDrone-YOLO/labels/train"train_image_dir = "/content/data/VisDrone-YOLO/images/train"val_label_dir = "/content/data/VisDrone-YOLO/labels/val"val_image_dir = "/content/data/VisDrone-YOLO/images/val"print("=== 检查训练集 ===")check_labels(train_label_dir, train_image_dir)print("\n=== 检查验证集 ===")check_labels(val_label_dir, val_image_dir)

        这段代码最后会输出标签是否对应好了,如果对应好了,就可以进入下一篇,模型训练了。


如果您觉得这篇文章对您有所帮助

欢迎点赞、转发、收藏,这将对我有非常大的帮助

感谢您的阅读,我们下篇文章再见~ 👋

http://www.lqws.cn/news/144505.html

相关文章:

  • 鸿蒙缺少WMIC missing WMIC
  • 《C++ 模板》
  • 仓库自动化搬运:自动叉车与AGV选型要点及核心技术解析
  • MyBatis之测试添加功能
  • 18650锂电池组点焊机:高效组装锂电池的关键工具|比斯特自动化
  • XDMA pcie环路测试
  • Oracle 的 SEC_CASE_SENSITIVE_LOGON 参数
  • 代码中文抽取工具并替换工具(以ts为例)
  • 在 CentOS 上将 Ansible 项目推送到 GitHub 的完整指南
  • 高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
  • [论文阅读] 人工智能+软件工程 | MemFL:给大模型装上“项目记忆”,让软件故障定位又快又准
  • [pdf、epub]300道《软件方法》强化自测题业务建模需求分析共257页(202505更新)
  • 机器学习监督学习实战四:九种回归算法对波士顿房价数据进行回归预测和评估方法可视化
  • 【从0-1的CSS】第1篇:CSS简介,选择器已经常用样式
  • centos部署k8s v1.33版本
  • asp.net mvc如何简化控制器逻辑
  • vue2 , el-select 多选树结构,可重名
  • 使用vite-plugin-html在 HTML 文件中动态注入数据,如元数据、环境变量、标题
  • Go中的协程并发和并发panic处理
  • MVCC机制:Undo Log版本链与ReadView机制
  • MVCC实现原理
  • bug 记录 - 使用 el-dialog 的 before-close 的坑
  • 网站首页菜单两种布局vue+elementui顶部和左侧栏导航
  • Pandas和Django的示例Demo
  • wpf Behaviors库实现支持多选操作进行后台绑定数据的ListView
  • MySQL 高可用基石 - 复制监控与常见 HA 方案
  • DBSyncer:开源数据库同步利器,MySQL/Oracle/ES/SqlServer/PG/
  • 企业培训学习考试系统源码 ThinkPHP框架+Uniapp支持多终端适配部署
  • 行列式的性质
  • exp1_code