Yolov8利用一代模型自动标注数据集实现方案

前言

  • 以前都是纯手动进行标注的,样本估计也就百来张,这回要训练的目标复杂了点,所以采集了有2000张左右的样本
  • 每张图片要标注的类别差不多6类,总不能直接手动标注2000张吧
  • 一个客户要的,我当时看到这么大工作量的时候内心是拒绝的,随口补了句:除非你自己标注,数据的训练以及后续工作可以交给我,他一口答应了,于是我就给了他100张样本,并在他电脑上给他部署了相关环境教他标注,第二天他就把标注好的数据集给我了
  • 于是我就用这100张样本数据训练出了一代模型,测试了下效果,竟然比预估的要好,每张图片的查全率基本有60%以上,正确率90%以上
  • 一般来说这样就基本可以达到投入使用的标准了,但是为了追求完美,我选择继续捣鼓下去,当然,并不是继续手动标注,而是研究自动标注

总体实现思路

  1. 标注少量数据集,30-50张样本数据,并训练出一代模型
  2. 写个一代模型批量推理预测的代码,如果条件允许的话,将一代模型部署成API接口(下面给出的代码就是基于API接口的)
  3. 将每张推理的类和类坐标范围提取出来,并按照一定的格式写入对应图片的txt文本

标注文件(*.txt)解析

只有了解标注文件写入的原理后,才能够正确地写入labelimg能够识别的格式~

每次标注完一张图片后,lables目录下就会自动生成一个对应图片名的txt文件,这就是标注的信息文件。一个类的大体格式如下:
0 0.222420 0.500735 0.188612 0.227941
第一位是类别索引,后面四位是边框界,都是以比例的形式

  • 类别索引(Class Index):
    第一个数字 0 代表被标注对象的类别索引。这个索引是对应于classes.txt中第一行的类别名,比如classes.txt第一行是猫,那么就代表0就代表猫

  • 边框界(Bounding Box)
    归一化的边界框坐标,格为 (中心点x坐标, 中心点y坐标, 宽度, 高度)。这些值是相对于图像尺寸的比例值,范围在 0 到 1 之间:

    • 中心点x坐标(0.222420):边界框中心的 x 坐标(相对于图像宽度的比例)。
    • 中心点y坐标(0.500735):边界框中心的 y 坐标(相对于图像高度的比例)。
    • 宽度(0.188612):边界框的宽度(相对于图像宽度的比例)。
    • 高度(0.227941):边界框的高度(相对于图像高度的比例)。

半自动标注实现代码

注意下面的detect函数就是推理预测的代码,需要自行根据自身情况修改!

import requests
from typing import List
import json
import base64
import os
from PIL import Image

def detect(image_path, model_name, img_size=640, conf=0.5, classes="all", download_image=True):
    url = "http://127.0.0.1:5678/detect" 
    files = {'file_list': open(image_path, 'rb')}
    data = {
        'modelName': model_name,
        'img_size': img_size,
        'conf': conf,
        'classes': classes,
        'download_image': download_image
    }

    response = requests.post(url, files=files, data=data)
    return response.text

def 自动标注():
    自动标注目标文件夹 = "C:\\Users\\daowuya\Desktop\\自动标注\\images\\train"
    自动标注结果文件夹 = "C:\\Users\\daowuya\Desktop\\自动标注\\labels\\train"
    模型名称 = "一代模型名称"
    n = 1
    all = os.listdir(自动标注目标文件夹)
    for i in all:
        print(f"正在标注第{n}/{len(all)}张图片 {i}")

        # 获取图像尺寸
        img_path = os.path.join(自动标注目标文件夹, i)
        with Image.open(img_path) as img:
            img_width, img_height = img.size

        result = detect(img_path, 模型名称)
        # 去除最外层的引号和方括号,并去除转义字符
        trimmed_str = result[2:-2].replace("\\", "")
        jsons = json.loads(trimmed_str)
        length = len(jsons)
        write_content = ""
        for j in range(length-1):
            if jsons[j]["confidence"] >= 0.9:
                # 获取类别索引和边界框信息
                class_index = jsons[j]["class"]
                bbox = jsons[j]["bbox"]  # [左上角x, 左上角y, 右下角x, 右下角y]

                # 计算中心点坐标及宽度和高度(归一化)
                x_center = ((bbox[0] + bbox[2]) / 2) / img_width
                y_center = ((bbox[1] + bbox[3]) / 2) / img_height
                width = (bbox[2] - bbox[0]) / img_width
                height = (bbox[3] - bbox[1]) / img_height

                # 构造写入内容
                write_content += f"{class_index} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n"

        # 写入文件
        txt_filename = os.path.splitext(i)[0] + ".txt"
        with open(os.path.join(自动标注结果文件夹, txt_filename), "w", encoding='utf-8') as file:
            file.write(write_content)
        n += 1

if __name__ == "__main__":
    自动标注()

lableimg打开自动标注的训练集报错解决

打开自动标注后的数据,出现下面的报错是必然的。经过摸索和亲身实践,都完美解决了,对应的报错我都给出了原因以及解决办法。

  • 报错1:

    Traceback (most recent call last):
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 738, in file_item_double_clicked
    self.load_file(filename)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1111, in load_file
    self.show_bounding_box_from_annotation_file(file_path)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1144, in show_bounding_box_from_annotation_file
    self.load_yolo_txt_by_filename(txt_path)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1557, in load_yolo_txt_by_filename
    t_yolo_parse_reader = YoloReader(txt_path, self.image)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\libs\yolo_io.py", line 101, in __init__
    self.classes = classes_file.read().strip('\n').split('\n')
    UnicodeDecodeError: 'gbk(或者utf-8)' codec can't decode byte 0x9e in position 18: illegal multibyte sequence

    原因:
    labelimg在每次更新classes后,我注意观察了下,即使你刚开始的classes.txt是utf-8编码的,但是在更新后都会变成ANSI编码的。
    解决方式:
    ①打开现有的classes.txt,并另存为ANSI编码的。
    ②进入labelimg的源代码目录,定位到报错的文件位置
    C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\libs\yolo_io.py
    报错的代码:

    classes_file = open(self.class_list_path, 'r')
    self.classes = classes_file.read().strip('\n').split('\n')

    修改成以ANSI编码打开文件

    with open(self.class_list_path, 'r', encoding='ANSI') as classes_file:
            self.classes = classes_file.read().strip('\n').split('\n')
  • 报错2

    Traceback (most recent call last):
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1376, in open_next_image
    self.load_file(filename)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1111, in load_file
    self.show_bounding_box_from_annotation_file(file_path)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1144, in show_bounding_box_from_annotation_file
    self.load_yolo_txt_by_filename(txt_path)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\labelImg\labelImg.py", line 1557, in load_yolo_txt_by_filename
    t_yolo_parse_reader = YoloReader(txt_path, self.image)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\libs\yolo_io.py", line 115, in __init__
    self.parse_yolo_format()
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\libs\yolo_io.py", line 146, in parse_yolo_format
    label, x_min, y_min, x_max, y_max = self.yolo_line_to_shape(class_index, x_center, y_center, w, h)
    File "C:\Users\daowuya\.conda\envs\labelimg\lib\site-packages\libs\yolo_io.py", line 128, in yolo_line_to_shape
    label = self.classes[int(class_index)]
    IndexError: list index out of range

    原因:
    这种情况正常打开查看标注情况是没有任何问题的,但是只要是修改或者增加了标注,此时再点击查看下一张图的标注情况就会发生闪退。这是因为在你更新数据后,classes.txt的数据会被重写,重写为上一张图里的所有class,所以一旦你的下一张图里原本标注的class不存在于classes.txt内,就会报“list index out of range”这种错误。
    解决方式:
    ①定位到labelimg.py源码目录
    C:\Users\daowuya\.conda\envs\labelimg\Lib\site-packages\labelImg
    ②在源码目录新建data文件夹,再在data文件夹里新建 predefined_classes.txt,注:这个txt文件的编码需要保存为utf-8。
    再将classes.txt里的所有内容都黏贴进去,保存即可!


作 者:道无涯
来 源:道无涯博客
链 接: https://www.daowuya.love/yolov8利用一代模型自动标注数据集实现方案/
版 权 声 明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议。文章版权归作者所有,未经允许请勿转载!


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇