学习系列三:V8目标检测与分割自动化标注

news2024/11/15 9:33:46

学习系列三:YOLOv8目标检测与分割自动化标注

提示:本次文章主要介绍yolov8目标检测与自动化标注(较简单,通用性比较强,标签格式txt),yolov8实例分割与自动化标注(程序较复杂,自动化标注效果有待提升,标签格式txt),大家有更好的想法可以在评论区进行交流。


文章目录

  • 学习系列三:YOLOv8目标检测与分割自动化标注
  • 一、YOLOv8训练目标检测数据集
    • 1.1 数据集的划分
    • 1.2 目标检测训练脚本
  • 二、实例化推理检测函数
  • 三、目标检查自动化标注与标签生成(txt格式)
  • 四、YOLOv8训练实例分割数据集
  • 五、实例化推理检测函数
  • 六、自动化标注与标签生成


一、YOLOv8训练目标检测数据集

1.1 数据集的划分

在进行训练目标检测数据前,需要划分训练集、验证集和测试集,可以进行人工的划分,可以使用代码进行自主进行划分,这里主要讲述使用代码进行自主划分训练集、验证集和测试集。
在划分之前需要看一下数据集的格式:数据集文件夹(tuoluo-aug), 数据集图片文件夹(images),数据集标签文件夹(labels, txt格式标签文件)
在这里插入图片描述

代码进行自主划分训练集、验证集和测试集。这里可以自己定义训练集、验证集和测试集所占比例多少。

from ultralytics.data.utils import autosplit

autosplit(
    path='/home/xiao/dataset/tuoluo-aug/images',
    weights=(0.8, 0.2, 0.00), # (train, validation, test) fractional splits
    annotated_only=False     # split only images with annotation file when True
)

运行之后在 tuoluo-aug文件下会生成txt文件,如下:
在这里插入图片描述

1.2 目标检测训练脚本

针对YOLOv8这里我写一个简单的脚本训练目标检测数据集,放在工程ultralytics-xiao下面,脚本文件名称定义为tuoluo.py,代码如下:

from ultralytics import YOLO


model = YOLO("/home/xiao/ultralytics-main/weights/yolov8n.pt") 
model.train(data="/home/xiao/ultralytics-main/ultralytics/cfg/datasets/bolt-detachment-aug.yaml",
                      epochs=120,
                      imgsz = 1280,
                      device= [0],
                      workers = 2,
                      batch =8,
                      patience=120
                      )

metrics = model.val()  # 在验证集上评估模型性能

在上述代码中数据集配置文件路径:“/home/xiao/ultralytics-main/ultralytics/cfg/datasets/bolt-detachment-aug.yaml”
配置文件内容为:

path: /home/xiao/dataset/tuoluo-aug/
train: autosplit_train.txt             
val: autosplit_val.txt                                           
test: autosplit_test.txt                                         

names:
  0: detachment


nc : 1

上述完成后,运行tuoluo.py即可开启训练。(上述数据集标签为:detachment)

二、实例化推理检测函数

针对上述训练完成后,会生成对应最好的权重,试用该权重进行推理新的图片,代码如下(封装成类函数了):

from ultralytics import YOLO
import cv2
import numpy as np
import time
import os


# 加载模型
model_file = './weight/best.pt'

model = YOLO(model_file)
objs_labels = model.names
print(objs_labels)


class yolo_demo:

    def __init__(self):

        self.model_file_1 = './weight/best.pt'

        self.model_1 = YOLO(self.model_file_1)

        self.objs_labels_1 = self.model_1.names


    def img_file_folder(self, img_folder):

        image_paths = []
        for image_name in os.listdir(img_folder):
            image_path = os.path.join(img_folder, image_name)
            if os.path.isfile(image_path) and image_name.lower().endswith(
                    ('.png', '.jpg', '.jpeg', '.bmp', '.tif', '.tiff')):
                image_paths.append(image_path)

        return image_paths

    def main(self, img_folder):

        for i, img_path in enumerate(self.img_file_folder(img_folder)):

            # 获取图片文件名
            img_id = img_path.split(os.sep)[-1].split('.')[0]

            # bgr
            image_bgr = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), -1)

            result = list(self.model_1(image_bgr, stream=True, conf=0.7))[0]
            boxes = result.boxes
            boxes = boxes.cpu().numpy()

            for box in boxes.data:
                l, t, r, b = box[:4].astype(np.int32)

                conf, id = box[4:]

                if id == 0:
                    # 绘制标签矩形框
                    cv2.rectangle(image_bgr, (l, t), (r, b), (0, 255, 0), 1)
                    label = "detachment"
                    cv2.putText(image_bgr, label, (l, t - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

            output_image_path = f"./output-v4/{img_id}.jpg"
            cv2.imwrite(output_image_path, image_bgr)


if __name__ =="__main__":

    plate_demo = yolo_demo()
    img_path = r"./detachment-images"

三、目标检查自动化标注与标签生成(txt格式)

适用于已经使用少量数据集图片进行YOLOv8训练,得到权重并使用该权重对新的数据集图片进行自动标注,后期可人工进行检查标注的好坏,进行简单修改,相比较于从头进行标注节省了大量的时间。

"""
yolov8 自动标注, 后续需要手工进行修改校准
"""
from ultralytics import YOLO
import cv2
import os
import numpy as np
import matplotlib.pyplot as plt
import glob
import shutil
import tqdm

# 加载模型
model_file = "./weights1to4/detachment.pt"
model = YOLO(model_file)
objs_labels = model.names
print(objs_labels)

# 读取图片
images_list = glob.glob('./img-detachment-9/*.jpg')

print(len(images_list))

# 创建标签文件夹
if not os.path.exists('./detachment-labels'):
    os.mkdir('./detachment-labels')

# 标注
def image_2_yolo():

    # 保存路径前缀
    savePathPrefix = "./detachment-labels/"

    # 遍历每张图片
    for img in images_list:

        # 获取图片文件名
        img_id = img.split(os.sep)[-1].split('.')[0]

        # 读取图片
        img_data = cv2.imread(img)
        # 检测
        result = list(model(img_data, stream=True, conf=0.5))[0]
        boxes = result.boxes
        boxes = boxes.cpu().numpy()

        yolo_boxes = []
        # 获取图片宽高
        img_h, img_w, _ = img_data.shape

        # 遍历每个框
        for box in boxes.data:

            l, t, r, b = box[:4].astype(np.int32)
            conf, id = box[4:]

            # 筛选出detachment类别, 转为yolo格式:类别id, x_center, y_center, width, height, 归一化到0-1, 保留6位小数
            if id == 0:
                class_label = int(id)
                x_center = round((l + r) / 2 / img_w, 6)
                y_center = round((t + b) / 2 / img_h, 6)
                width = round((r - l) / img_w, 6)
                height = round((b - t) / img_h, 6)

                yolo_boxes.append([class_label, x_center, y_center, width, height])

        # 写入txt文件
        # 生成yolo格式的标注文件
        yoloLabelFile = savePathPrefix + img_id + '.txt'
        with open(yoloLabelFile, 'w') as f:
            for yolo_box in yolo_boxes:
                f.write(' '.join([str(i) for i in yolo_box]) + '\n')


if __name__ == '__main__':
    image_2_yolo()

四、YOLOv8训练实例分割数据集

from ultralytics import YOLO


model = YOLO('/home/hxz/xiao/ultralytics-xiao/ultralytics/cfg/models/v8/yolov8-seg.yaml').load('/home/hxz/xiao/ultralytics-xiao/runs/segment/train6/weights/best.pt')


model.train(data="/home/hxz/xiao/ultralytics-xiao/ultralytics/cfg/datasets/seg-bolt-line-cz933-weitiao.yaml",
            task="segment",
            mode="train",
            overlap_mask=False,
            batch=16,
            device=0,
            epochs=600,
            patience=600,
            imgsz=128)

metrics = model.val(iou=0.7)


try:
    a = metrics.box.map               # map50-95
    b = metrics.box.map50             # map50
    c = metrics.box.map75             # map75
    d = metrics.box.maps              # 返回一个列表,包含每个类别的mAP值(IoU在0.5到0.95)
    print("result:", a, b, c, d)

except Exception as e:
    print('f{有一些问题}')

五、实例化推理检测函数

from ultralytics import YOLO

# Load a model
model = YOLO("/home/hxz/xiao/ultralytics-xiao/runs/segment/train6/weights/best.pt")  # load a custom model

# Predict with the model
source = "/home/hxz/xiao/ultralytics-xiao/test-img" # predict on an image

results = model.predict(source, save=True)

六、自动化标注与标签生成

这部分是根据比较少的数据集训练得到的数据的权重,根据权重区预测新的图片,获得mask,根据mask读取坐标保存至txt文件。

from ultralytics import YOLO
import numpy as np
import cv2
import os
import matplotlib.pyplot as plt
import glob


# 加载分割模型
model = YOLO("./weights/fks-seg.pt")  # 加载自定义模型

# 预测源
image_folder = r"./fks-seg/images"

# 获取文件夹中所有图片的路径
image_paths = glob.glob(os.path.join(image_folder, "*.jpg"))

# 保存分割结果坐标点的目录
output_dir = "./fks-seg/txt_labels"
os.makedirs(output_dir, exist_ok=True)


for image_path in image_paths:

    results = model.predict(image_path)

    base_name = os.path.basename(image_path).split('.')[0]

    # 创建输出文件路径
    txt_filename = os.path.join(output_dir, f"{base_name}.txt")

    for result in results:
        masks = result.masks  # 获取分割掩码
        classes = result.boxes.cls if result.boxes is not None else []  # 获取每个掩码的类别

        # 获取图像的宽度和高度以进行归一化
        height, width = result.orig_img.shape[:2]
        print(height, width)

        # 创建输出文件路径
        txt_filename = os.path.join(output_dir, f"{os.path.basename(result.path).split('.')[0]}.txt")

        with open(txt_filename, 'w') as f:
            if masks is not None:
                for i, mask in enumerate(masks.data):
                    # 将 PyTorch 张量转换为 NumPy 数组并确保掩码是二值图像
                    mask = mask.cpu().numpy().astype(np.uint8)

                    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

                    # 获取当前掩码对应的类别
                    class_id = int(classes[i]) if i < len(classes) else -1

                    # 准备一个列表来存储该类别的所有归一化坐标
                    coordinates = []

                    for contour in contours:

                        # 将轮廓的坐标点进行归一化
                        normalized_coordinates = []
                        for point in contour:
                            x, y = point[0]
                            x_normalized = x / mask.shape[1]
                            y_normalized = y / mask.shape[0]
                            normalized_coordinates.append(f"{x_normalized:.6f} {y_normalized:.6f}")

                        # 获取当前掩码对应的类别
                        class_id = int(classes[i]) if i < len(classes) else -1

                        # 写入 YOLO 格式的标签文件(类别 + 轮廓坐标)
                        if normalized_coordinates:
                            f.write(f"{class_id} " + " ".join(normalized_coordinates) + "\n")

                    print(f"Saved YOLO segmentation coordinates to {txt_filename}")



将生成的txt文件转json后,把图片和生成的json文件放在同一个文件夹,可在lableme中查看自动标注的情况。

import os
import json
import cv2
import numpy as np
import glob


def yolo_to_labelme(txt_file, img_file, class_names, output_json):
    if not os.path.exists(txt_file):
        print(f"File {txt_file} does not exist.")
        return

    img = cv2.imdecode(np.fromfile(img_file, dtype=np.uint8), -1)
    height, width = img.shape[:2]

    shapes = []

    with open(txt_file, 'r') as f:
        lines = f.readlines()

        for line in lines:
            parts = line.strip().split()
            class_id = int(parts[0])
            # 将归一化的坐标转换为非归一化的像素坐标
            points = [(float(parts[i]) * width, float(parts[i + 1]) * height) for i in range(1, len(parts), 2)]

            shape = {
                "label": class_names[class_id],
                "points": points,
                "group_id": None,
                "shape_type": "polygon",
                "flags": {}
            }
            shapes.append(shape)

    labelme_data = {
        "version": "4.5.6",
        "flags": {},
        "shapes": shapes,
        "imagePath": os.path.basename(img_file),
        "imageData": None,
        "imageHeight": height,
        "imageWidth": width
    }

    with open(output_json, 'w') as f:
        json.dump(labelme_data, f, indent=4)
    print(f"Saved JSON to {output_json}")


def batch_process_yolo_to_labelme(image_folder, label_folder, output_folder, class_names):
    os.makedirs(output_folder, exist_ok=True)

    # 获取所有的图片文件
    image_files = glob.glob(os.path.join(image_folder, "*.jpg"))

    for img_file in image_files:
        # 获取对应的 txt 文件
        base_name = os.path.basename(img_file).split('.')[0]
        txt_file = os.path.join(label_folder, f"{base_name}.txt")

        # 输出的 JSON 文件路径
        output_json = os.path.join(output_folder, f"{base_name}.json")

        # 转换 YOLO 到 LabelMe 格式
        yolo_to_labelme(txt_file, img_file, class_names, output_json)


# 示例使用
class_names = ["red"]  # 根据你的类别顺序填写
image_folder = r"./fks-seg/images"
label_folder = r"./fks-seg/txt_labels"
output_folder = r"./fks-seg/json_labels"

batch_process_yolo_to_labelme(image_folder, label_folder, output_folder, class_names)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2076792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SE11 没有激活的名称表存 No active nametab exists for

背景&#xff1a; SE11中减少某个非空表的字段的长度后&#xff0c;在SE14中的操作不当&#xff0c;并且对该表进行了删除重建的操作后&#xff0c;发生SE11激活该表报错。 原因&#xff1a; 出现了一些未知原因&#xff0c;导致该表在底层数据库存在&#xff0c;但是运行时对…

柔版印刷版市场前景:预计2030年全球市场规模将达到20.9亿美元

一、当前市场状况 目前&#xff0c;柔版印刷版市场呈现出较为稳定的发展态势。随着全球经济的逐步复苏&#xff0c;包装印刷等领域对柔版印刷版的需求持续增长。柔版印刷版具有环保、高效、印刷质量高等特点&#xff0c;在食品包装、标签印刷等行业中得到广泛应用。 全球前四…

微信聊天记录删除怎么恢复?两个抱藏方法快速恢复数据

微信作为我们日常沟通的重要工具&#xff0c;存储了大量的聊天记录&#xff0c;这些记录往往承载着珍贵的记忆或重要的工作信息。我们在日常使用微信时不小心左滑删除了和领导的聊天记录&#xff01;里面还有很重要的工作内容&#xff0c;删除的微信聊天记录怎么恢复啊&#xf…

环境问题处理:Python写工具,转换excel内容合并到xml中(openpyxllxml)

问题描述 提示报错&#xff0c;但是没有像java代码的解决方案推荐。 Note&#xff1a;PycharmProjects\项目名\venv\Scripts 创建项目时自带的脚本&#xff0c;也包含python.exe 查看python文件有输出路径&#xff0c;使用python也能打开python3.8&#xff0c;但是无法查找pyt…

Java学习_22_网络编程

文章目录 前言网络编程网络编程三要素IPInetAddress 端口号协议OSI七层模型TCP/IP模型UDP协议TCP协议 综合练习多发多收接收和反馈上传文件上传文件重名问题上传文件多线程问题上传文件线程池问题BS架构 总结 前言 博客仅记录个人学习进度和一些查缺补漏。 学习内容&#xff1…

软考:一个月拿下软件设计师

前言 软考我满打满算也就准备了一个月不到&#xff0c;期间也走了不少弯路&#xff1b;特地做个博客记录一下&#xff0c;也给其它备考的人一些建议。 我是24年上半年参加的考试&#xff0c;说实在的这年下午题有几道不好写。 只要上午成绩和下午成绩都过45就算及格了。 正文…

【Git保姆级使用教程】Git从入门到精通超级详细的使用教程,一套教程带你搞定Git(高见龙版本)。

目录 Git下载与安装设置GitGit的用户设置 使用Git新增初始Repository将文件交给Git管控(将文件加入暂存区)查看Git文件记录查找commit记录更改提交commit的记录撤销提交commit 将某些文件取消Git版控Git中删除或更改文件名Git查看某个文件的某一行代码是谁写的.git目录中有什么…

Tower for Mac Git客户端管理软件

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试1、打开软件&#xff0c;测试2、克隆项目&#xff0c;测试 安装完成&#xf…

港股震荡中保持乐观,市场信心回来了!

港股上午盘三大指数集体上涨&#xff0c;恒生科技指数一度冲高至1.54%&#xff0c;最终收涨0.98%&#xff0c;恒生指数上涨1.06%。盘面上&#xff0c;大型科技股多数维持上涨行情&#xff0c;百度、腾讯涨超1.5%&#xff0c;快手、美团小幅上涨&#xff0c;阿里巴巴、京东飘绿&…

Java:Date类

文章目录 Date类常用方法代码演示 SimpleDateFormat常用方法代码演示时间格式常见符号SimpleDateFormat解析字符串为Date对象代码总结 案例&#xff1a;秒杀活动&#xff1a; 黑马学习笔记 这些方法在API文档都能查到 Date类 常用方法 代码演示 package Time;import java.uti…

杰发科技AC7801——Flash模拟EEP内存(2)

1. 默认配置在1000个地址存储1000个数据 配置如下 计算地址 查看地址内容&#xff0c;等到打印完成 计算符合&#xff0c;从0-999共计1000 2. 修改配置在65536地址存储65536个数据 配置还是这个 因为传进去的地址是uint16_t&#xff0c;因此最大值是65536&#xff0c;写65536…

mp总结 mybatisPlus

一、准备 1.引入依赖&#xff08;引入后可以不再引mybatis依赖&#xff09; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version> </dependency> 2.…

Leetcode JAVA刷刷站(95)不同的二叉搜索数 ||

一、题目概述 二、思路方向 为了生成所有由 n 个节点&#xff08;值从 1 到 n&#xff09;组成的不同二叉搜索树&#xff08;BST&#xff09;&#xff0c;我们可以采用递归的方式。核心思想在于&#xff0c;对于每个数字 i&#xff08;从 1 到 n&#xff09;&#xff0c;我们可…

【C语言报错已解决】 `Buffer Overflow`

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言一、问题描述&#x1f469;‍&#x1f52c;报错示例&#x1f4da;报错分析&#x1f4da;解决思路 二、解决方法&a…

麒麟V10(x86_64)安装部署MySQL-5.1.70

麒麟V10(x86_64)安装部署MySQL-5.1.70 1. 主机信息 [kalamikysrv1 ~]$ uname -a Linux kysrv1 4.19.90-24.4.v2101.ky10.x86_64 #1 SMP Mon May 24 12:14:55 CST 2021 x86_64 x86_64 x86_64 GNU/Linux [kalamikysrv1 ~]$ [kalamikysrv1 ~]$ uname -m x86_64 [kalamikysrv1 ~…

深度学习模板方法设计模式

文章目录 前言一、介绍二、特点三、详细介绍1.核心组成2.代码示例3.优缺点优点缺点 4.使用场景 总结 前言 模板方法设计模式是行为型设计模式&#xff0c;主要是定义算法框架&#xff0c;并将一些步骤的实现延迟到子类&#xff0c;重新定义算法的步骤。 一、介绍 模板设计模式…

项目初始化踩坑记录

dependence not found: D:/yupiProject/yubi-bi-frontend/node_modules/umijs/plugins/node_modules/react-intl 这个没有在github上找到解决方法&#xff0c;于是我在命令行 npm install 执行这个之后&#xff0c;就可以重新运行了 思考过程&#xff1a;突然空了个文件我…

开放式耳机是什么意思?开放式耳机推荐

在探讨音频设备的广阔领域中&#xff0c;开放式耳机以其独特的设计理念和卓越的性能体验&#xff0c;逐渐成为耳机市场上一股不可忽视的力量。顾名思义&#xff0c;开放式耳机是一种采用开放式设计&#xff0c;不堵塞或覆盖耳朵&#xff0c;允许佩戴者同时听到部分外部声音的耳…

Unity滚滚车轮计划 之 新输入系统控制2D角色移动动画(俯视)

本系列的初衷是因为很多时候基础代码不得不重复又重复&#xff0c;所以为了更快更好地学习到新的知识&#xff0c;我就把已经掌握的知识造成自己的轮子吧&#xff0c;等用到的时候直接复制就行了 叠甲&#xff1a;虽然不能保证全是原创&#xff0c;有些写法可能烂大街&#xff…

arm64--内嵌汇编

内嵌汇编代码基本用法 1.作用&#xff1a;对于特定重要和时间敏感的代码进行优化&#xff0c;同时在C语言中访问某些特殊指令&#xff08;例如内存屏障指令&#xff09;来实现特殊功能 2.内嵌汇编代码主要有两种形式 基础内嵌汇编代码&#xff1a;不带任何参数 扩展内嵌汇…