小目标的检测指标APs怎么获得?------数据集Yolo格式生成json文件

        这么简单的东西,但是莫名其妙搞了好几天,很抑郁,话不多说直接开始。
        首先你得有YoLo格式的数据集,从最简单的开始,需要有图片数据和对应的yolo类型的txt标签数据。(下面截图中第一个文件夹是存放图片,命名规则用纯数字,后一个文件夹是txt文件,对应与每一张图片的检测标签)。

        有了这两个文件夹之后,第一步,划分数据集。将图片数据集划分成8:2。所使用到的代码如下:

import os
import shutil
import random
from tqdm import tqdm

"""
标注文件是yolo格式(txt文件)
训练集:验证集 (8:2) 
"""


def split_img(img_path, label_path, split_list):
    try:  # 创建数据集文件夹
        Data = 'D:\datasets\small-object-detection-datasets\Solar_1103\ImageSets'
        # os.mkdir(Data)

        train_img_dir = Data + '/images/train'
        val_img_dir = Data + '/images/val'
        # test_img_dir = Data + '/images/test'

        train_label_dir = Data + '/labels/train'
        val_label_dir = Data + '/labels/val'
        # test_label_dir = Data + '/labels/test'

        # 创建文件夹
        os.makedirs(train_img_dir)
        os.makedirs(train_label_dir)
        os.makedirs(val_img_dir)
        os.makedirs(val_label_dir)
        # os.makedirs(test_img_dir)
        # os.makedirs(test_label_dir)

    except:
        print('文件目录已存在')

    train, val = split_list
    all_img = os.listdir(img_path)
    all_img_path = [os.path.join(img_path, img) for img in all_img]
    # all_label = os.listdir(label_path)
    # all_label_path = [os.path.join(label_path, label) for label in all_label]
    train_img = random.sample(all_img_path, int(train * len(all_img_path)))
    train_img_copy = [os.path.join(train_img_dir, img.split('\\')[-1]) for img in train_img]
    train_label = [toLabelPath(img, label_path) for img in train_img]
    train_label_copy = [os.path.join(train_label_dir, label.split('\\')[-1]) for label in train_label]
    for i in tqdm(range(len(train_img)), desc='train ', ncols=80, unit='img'):
        _copy(train_img[i], train_img_dir)
        _copy(train_label[i], train_label_dir)
        all_img_path.remove(train_img[i])
    val_img = all_img_path
    val_label = [toLabelPath(img, label_path) for img in val_img]
    for i in tqdm(range(len(val_img)), desc='val ', ncols=80, unit='img'):
        _copy(val_img[i], val_img_dir)
        _copy(val_label[i], val_label_dir)


def _copy(from_path, to_path):
    shutil.copy(from_path, to_path)


def toLabelPath(img_path, label_path):
    img = img_path.split('\\')[-1]
    label = img.split('.tiff')[0] + '.txt'
    return os.path.join(label_path, label)


if __name__ == '__main__':
    #修改成自己的图片路径
    img_path = 'D:\datasets\small-object-detection-datasets/aluminum_1103\JPEGImages'
    #修改成自己的标签路径
    label_path = 'D:\datasets\small-object-detection-datasets/aluminum_1103\labels'
    split_list = [0.8, 0.2]  # 数据集划分比例[train:val]
    split_img(img_path, label_path, split_list)

ok,现在多了一个这个文件夹

里面的结构如下:

imageSets
images
train里面存放训练集的图片
val里面存放验证集的图片
labels
train里面存放训练集的标签
val里面存放验证集的标签

接下来生成train.txt和val.txt(这两个文件是yolov5读取图片路径的文件),代码如下:

import os
#TODO:需要改动的地方就是三个路径地址,因为是要生成train.txt和val.txt所以要执行两次

# 指定B文件夹的路径
folder_B = 'D:\datasets\small-object-detection-datasets\Solar_1103\ImageSets\images/train'

# 获取B文件夹下的所有图片文件
image_files = [f for f in os.listdir(folder_B) if f.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff'))]

# 创建train.txt文件并写入图片文件名
with open('D:\datasets\small-object-detection-datasets\Solar_1103/train.txt', 'w') as file:
    for image_file in image_files:
        # image_files_myhouzhui = image_file[:6] +".txt"   #切分后缀
        file.write("D:\datasets\small-object-detection-datasets\Solar_1103\JPEGImages/"+image_file + '\n')

print('train.txt 文件已创建并写入图片文件名')

这样之后你就有五个文件了:

解下来就是生成json文件的最后一步,运行yolo转COCO脚本,代码如下:

import os
import json
import random
import time
from PIL import Image
import csv
#TODO:下面四个路径是需要对应修改的、除此之外class_names这个列表的内容修改成自己数据的类别
coco_format_save_path = 'D:\datasets\small-object-detection-datasets\Solar_1103'  # 要生成的标准coco格式标签所在文件夹
yolo_format_annotation_path = 'D:\datasets\small-object-detection-datasets\Solar_1103\ImageSets\labels/val'  # yolo格式标签所在文件夹
img_pathDir = 'D:\datasets\small-object-detection-datasets\Solar_1103\JPEGImages'  # 图片所在文件夹
val_img_pathDir = 'D:\datasets\small-object-detection-datasets\Solar_1103\ImageSets\images/val'
# 类别设置
categories = []
class_names = ['bl', 'ce', 'ch', 'cr', 'hi', 'ir',  'oi', 'pe']     #需要修改成自己的类别
for label in class_names:
    categories.append({'id': class_names.index(label), 'name': label, 'supercategory': ""})

write_json_context = dict()  # 写入.json文件的大字典
write_json_context['licenses'] = [{'name': "", 'id': 0, 'url': ""}]
write_json_context['info'] = {'contributor': "", 'date_created': "", 'description': "", 'url': "", 'version': "", 'year': ""}
write_json_context['categories'] = categories
write_json_context['images'] = []
write_json_context['annotations'] = []

# 接下来的代码主要添加'images'和'annotations'的key值
imageFileList = os.listdir(img_pathDir)
#按照数字来进行排序
def sort_list_by_number(strings):
    def extract_number(s):
        # 从字符串中提取数字部分
        return int(''.join(filter(str.isdigit, s)))

        # 使用自定义的排序键对字符串列表进行排序
    sorted_strings = sorted(strings, key=extract_number)

    return sorted_strings
imageFileList = sort_list_by_number(imageFileList)
'''
    再新创建一个只有val文件夹的列表进行二次判断!!
'''
val_imageFile = os.listdir(val_img_pathDir)
val_imageFile = sort_list_by_number(val_imageFile)
# 遍历该文件夹下的所有文件,并将所有文件名添加到列表中
img_id = 0  # 图片编号
anno_id = 0     # 标注标号
for i, imageFile in enumerate(imageFileList):
    if '_' not in imageFile:
        img_id += 1
        if imageFile in val_imageFile:
            imagePath = os.path.join(img_pathDir, imageFile)  # 获取图片的绝对路径
            image = Image.open(imagePath)  # 读取图片
            W, H = image.size  # 获取图片的高度宽度
            img_context = {}  # 使用一个字典存储该图片信息
            # img_name=os.path.basename(imagePath)
            img_context['id'] = img_id  # 每张图像的唯一ID索引
            img_context['width'] = W
            img_context['height'] = H
            img_context['file_name'] = imageFile
            img_context['license'] = 0
            img_context['flickr_url'] = ""
            img_context['color_url'] = ""
            img_context['date_captured'] = ""

            write_json_context['images'].append(img_context)  # 将该图片信息添加到'image'列表中

            txtFile = imageFile.split('.')[0] + '.txt'  # 获取该图片获取的txt文件
            with open(os.path.join(yolo_format_annotation_path, txtFile), 'r') as fr:
                lines = fr.readlines()  # 读取txt文件的每一行数据,lines2是一个列表,包含了一个图片的所有标注信息

            for j, line in enumerate(lines):
                anno_id += 1  # 标注的id从1开始
                bbox_dict = {}  # 将每一个bounding box信息存储在该字典中

                class_id, x, y, w, h = line.strip().split(' ')  # 获取每一个标注框的详细信息
                class_id, x, y, w, h = int(class_id), float(x), float(y), float(w), float(h)  # 将字符串类型转为可计算的int和float类型

                # 坐标转换
                xmin = (x - w / 2) * W
                ymin = (y - h / 2) * H
                xmax = (x + w / 2) * W
                ymax = (y + h / 2) * H
                w = w * W
                h = h * H
                height, width = abs(ymax - ymin), abs(xmax - xmin)

                # bounding box的坐标信息
                bbox_dict['id'] = anno_id               # 每个标注信息的索引
                bbox_dict['image_id'] = img_id          # 当前图像的ID索引
                bbox_dict['category_id'] = class_id     # 类别信息
                bbox_dict['segmentation'] = [[xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax]]
                bbox_dict['area'] = height * width
                bbox_dict['bbox'] = [xmin, ymin, w, h]  # 注意目标类别要加一
                bbox_dict['iscrowd'] = 0
                bbox_dict['attributes'] = ""

                write_json_context['annotations'].append(bbox_dict)  # 将每一个由字典存储的bounding box信息添加到'annotations'列表中

name = os.path.join(coco_format_save_path, "annotations" + '.json')
with open(name, 'w') as fw:  # 将字典信息写入.json文件中
    json.dump(write_json_context, fw, indent=4, ensure_ascii=False)

这样就可以获得这个json文件。

对这个文件进行说明一下,并讲解一下为什么要这个文件。

        json文件是对数据集中验证集(即val文件夹中的图片进行描述,以及它的坐标的描述--还有其他东西,但做小目标检测指标知道这个就足够了)。

        需要这个文件是因为,你在使用val.py文件进行APs的指标评估的时候,会生成一个best.json,那个json文件包含了你对验证集中图片的检测信息,其实就是你生成的检测框的信息,将best.json和annotations.json进行对比就可以得到APs的检测指标了。

        贴一个成功的图片:

------注意要调用val.py执行COCO检测指标时还需要修改val.py中的三处代码,今天没什么时间了,先放着(自行搜索一下,这个好搜),等有空了我会贴链接,现在懒得找了。

------图片标注完之后是json格式的文件,要生成yolo的txt文件可以参考我这一篇博客记录一下labelme标注完之后生成yolo的txt格式标签-CSDN博客

------另外注意,ImageSets的这个文件夹,在生成完json文件之后可以删掉了,你用yolo跑检测的话不需要用到它。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值