【14】模型训练自制数据集前的一些数据处理操作

辅助工具

      • 坏图像扫描与检查
      • 所有文件连续重命名排号
      • 划分数据集为训练集、测试集和验证集
      • 将标注的json文件转换成yolo格式文件,即txt文件
      • 将xml格式文件转换成yolo格式可读取的文件
      • 将gt后缀的图像数据文件进行解析
      • 统计yolo存储文件下各类标签下所对应标注目标的数量,累积打印数据分布情况

坏图像扫描与检查

import os
import cv2

# 检查的图像数据和保存的路径设置一样,则会检测出坏图像
dataDir = r"/home/s22030812007/faster-rcnn-pytorch/VOCdevkit1/VOC2007/JPEGImages/"
saveDir = r"/home/s22030812007/faster-rcnn-pytorch/VOCdevkit1/VOC2007/JPEGImages/"

if not os.path.exists(saveDir):
    os.makedirs(saveDir)
c = 0
for one_pic in os.listdir(dataDir):
    one_path = dataDir + one_pic
    one_img = cv2.imread(one_path)
    new_path = saveDir + one_pic
    d = cv2.imwrite(new_path, one_img)
    c = c + 1
    print(d, c)

所有文件连续重命名排号

import os
if __name__ == '__main__':
    path = r"C:/Users/27801/Documents/Datasets/5551"  # 需要出来的图片文件所在路径(即文件夹路径),注意斜杠的方向
    file_names = os.listdir(path)  # 获取该文件夹下所有的文件名称(包括文件夹)
    print(f'file_names:{file_names}')
    count = 6563  # 设置变量count,为重命名文件的起始编号
    for file in file_names:  # 遍历所有文件名
        print(f"file:{file}")
        old_name = os.path.join(path, file)
        print(f'old_name:{old_name}')
        if os.path.isdir(old_name):  # 如果是文件夹则跳过
            continue
        filename = os.path.splitext(file)[0]  # 文件名
        filetype = os.path.splitext(file)[1]  # 文件扩展名
        new_name = os.path.join(path, str(count).zfill(6) + filetype)  # 用字符串函数zfill 以0补全所需位数
        print(f'new_name:{new_name}')
        os.rename(old_name, new_name)  # 重命名 用新的文件名代替旧的文件名
        count += 1  # count的作用是给文件名计数的,以及累积的步幅

划分数据集为训练集、测试集和验证集

import os, shutil, random

random.seed(201)
import numpy as np
from sklearn.model_selection import train_test_split

# 验证集、测试集的占比,剩余的比例为训练集数据,0.1为占比百分之十
val_size = 0.1
test_size = 0.1
postfix = 'jpg'

# 图像数据的路径
imgpath = r'C:/Users/27801/Desktop/JPEGImages/'

#txt后缀的文件路径
txtpath = r'C:/Users/27801/Desktop/txts/'

#创建目录文件夹,用于存放划分数据后的图像,且若不存在则自动创建文件夹
os.makedirs('Logos3/images/train', exist_ok=True)
os.makedirs('Logos3/images/val', exist_ok=True)
os.makedirs('Logos3/images/test', exist_ok=True)
os.makedirs('Logos3/labels/train', exist_ok=True)
os.makedirs('Logos3/labels/val', exist_ok=True)
os.makedirs('Logos3/labels/test', exist_ok=True)

# 列出txtpath目录下所有包含'txt'字符串的文件名  将这些文件名存储在一个列表中
listdir = np.array([i for i in os.listdir(txtpath) if 'txt' in i])

# 随机打乱列表中文件名
random.shuffle(listdir)
# 按照比例划分
train, val, test = listdir[:int(len(listdir) * (1 - val_size - test_size))], \
    listdir[int(len(listdir) * (1 - val_size - test_size)):int(len(listdir) * (1 - test_size))], \
    listdir[int(len(listdir) * (1 - test_size)):]
print(f'train set size:{len(train)} val set size:{len(val)} test set size:{len(test)}')

# 将分配好的文件进行转移到指定文件夹下
for i in train:
    shutil.copy('{}/{}.{}'.format(imgpath, i[:-4], postfix), 'Logos3/images/train/{}.{}'.format(i[:-4], postfix))
    shutil.copy('{}/{}'.format(txtpath, i), 'Logos3/labels/train/{}'.format(i))

for i in val:
    shutil.copy('{}/{}.{}'.format(imgpath, i[:-4], postfix), 'Logos3/images/val/{}.{}'.format(i[:-4], postfix))
    shutil.copy('{}/{}'.format(txtpath, i), 'Logos3/labels/val/{}'.format(i))

for i in test:
    shutil.copy('{}/{}.{}'.format(imgpath, i[:-4], postfix), 'Logos3/images/test/{}.{}'.format(i[:-4], postfix))
    shutil.copy('{}/{}'.format(txtpath, i), 'Logos3/labels/test/{}'.format(i))

将标注的json文件转换成yolo格式文件,即txt文件

import json
import os

## json格式转换成yolo格式
# 设置:标签对应的编号
# !!!一定要查看自己标注数据集时对应的编号
name2id = {'figure': 0, 'text': 1, 'mix': 2}

def convert(img_size, box):
    dw = 1. / (img_size[0])
    dh = 1. / (img_size[1])
    x = (box[0] + box[2]) / 2.0 - 1
    y = (box[1] + box[3]) / 2.0 - 1
    w = box[2] - box[0]
    h = box[3] - box[1]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def decode_json(json_folder_path, json_name):

    # 设置:转换好格式后的标签存放的路径
    txt_name = 'C:/Users/27801/Documents/Datasets/mydata/txt/' + json_name[0:-5] + '.txt'
    txt_file = open(txt_name, 'w')

    json_path = os.path.join(json_folder_path, json_name)
    data = json.load(open(json_path, 'r', encoding='gb2312'))

    img_w = data['imageWidth']
    img_h = data['imageHeight']

    for i in data['shapes']:
        label_name = i['label']
        if (i['shape_type'] == 'rectangle'):
            x1 = int(i['points'][0][0])
            y1 = int(i['points'][0][1])
            x2 = int(i['points'][1][0])
            y2 = int(i['points'][1][1])

            bb = (x1, y1, x2, y2)
            bbox = convert((img_w, img_h), bb)
            txt_file.write(str(name2id[label_name]) + " " + " ".join([str(a) for a in bbox]) + '\n')

if __name__ == "__main__":

    # 路径设置:需要进行格式转换的.json文件夹存放路径
    json_folder_path = 'C:/Users/27801/Documents/Datasets/mydata/labels'
    json_names = os.listdir(json_folder_path)
    for json_name in json_names:
        decode_json(json_folder_path, json_name)

将xml格式文件转换成yolo格式可读取的文件

import cv2
import os
import xml.etree.ElementTree as ET
import numpy as np

classes = ['text', 'mix', 'figure']

def convert(size, box):
    dw = 1. / (size[0])
    dh = 1. / (size[1])
    x = (box[0] + box[1]) / 2.0 - 1
    y = (box[2] + box[3]) / 2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)

def convert_annotation(xmlpath, xmlname):
    with open(xmlpath, "r", encoding='utf-8') as in_file:
        txtname = xmlname[:-4] + '.txt'
        txtfile = os.path.join(txtpath, txtname)
        tree = ET.parse(in_file)
        root = tree.getroot()
        filename = root.find('filename')
        img = cv2.imdecode(np.fromfile('{}/{}.{}'.format(imgpath, xmlname[:-4], postfix), np.uint8), cv2.IMREAD_COLOR)
        h, w = img.shape[:2]
        res = []
        for obj in root.iter('object'):
            cls = obj.find('name').text
            if cls not in classes:
                classes.append(cls)
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            bb = convert((w, h), b)
            res.append(str(cls_id) + " " + " ".join([str(a) for a in bb]))
        if len(res) != 0:
            with open(txtfile, 'w+') as f:
                f.write('\n'.join(res))

if __name__ == "__main__":
    # 图像后缀为jpg,图像文件路径、xml标注文件路径
    postfix = 'jpg'
    imgpath = r'C:/Users/27801/Desktop/JPEGImages/'
    xmlpath = r'C:/Users/27801/Desktop/Annotations/'

    # txt为yolo的表现格式,若没有存在,则自动创建文件夹
    txtpath = r'C:/Users/27801/Desktop/txts/'

    if not os.path.exists(txtpath):
        os.makedirs(txtpath, exist_ok=True)

    list = os.listdir(xmlpath)
    error_file_list = []
    for i in range(0, len(list)):
        try:
            path = os.path.join(xmlpath, list[i])
            if ('.xml' in path) or ('.XML' in path):
                convert_annotation(path, list[i])
                print(f'file {list[i]} convert success.')
            else:
                print(f'file {list[i]} is not xml format.')
        except Exception as e:
            print(f'file {list[i]} convert error.')
            print(f'error message:\n{e}')
            error_file_list.append(list[i])
    print(f'this file convert failure\n{error_file_list}')
    print(f'Dataset Classes:{classes}')

将gt后缀的图像数据文件进行解析

if __name__ == "__main__":
    # 下载的数据为gt格式存放
    label_path = r'C:\Users\27801\Desktop\BelgaLogos\qset3_internal_and_local.gt'
    labels_origin = []
    with open(label_path, "r") as f:
        for line in f.readlines():
            l = " ".join(line.split("\t"))
            labels_origin.append(l.strip("\n"))
    imgs_label = {}
    # 数据包括的所有标签
    classes = [['Adidas', 'Adidas-text', 'Airness', 'Base', 'BFGoodrich', 'Bik', 'Bouigues', 'Bridgestone',
                'Bridgestone-text', 'Carglass', 'Citroen', 'Citroen-text', 'CocaCola', 'Cofidis', 'Dexia',
                'ELeclerc', 'Ferrari', 'Gucci', 'Kia', 'Mercedes', 'Nike', 'Peugeot', 'Puma', 'Puma-text',
                'Quick', 'Reebok', 'Roche', 'Shell', 'SNCF', 'Standard_Liege', 'StellaArtois', 'TNT',
                'Total', 'Umbro', 'US_President', 'Veolia', 'VRT']]
    for i in labels_origin:
        if i.split()[2] not in imgs_label.keys():
            imgs_label[i.split()[2]] = []
        if i.split()[1] not in classes:
            classes.append(i.split()[1])
        imgs_label[i.split()[2]].append(
            [int(i.split()[5]), int(i.split()[6]), int(i.split()[7]), int(i.split()[8]), i.split()[1]])
    print('imgs_label', imgs_label)

统计yolo存储文件下各类标签下所对应标注目标的数量,累积打印数据分布情况

import matplotlib.pyplot as plt
import os

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

cn_path = open(r"C:\Users\27801\Desktop\BelgaLogos\classes.txt")  # 存有类别的文本路径,如:"C:/Users/Admin/Desktop/classes.txt"

classes = [i.replace("\n", "") for i in cn_path.readlines()]
print(classes)

class_dict = {i: 0 for i in classes}
print("类别数", len(class_dict))

def main(base_path):
    # 列出指定路径base_path下的所有文件和目录名
    fileList = os.listdir(base_path)
    for file in fileList:
        if file == "classes.txt":
            continue
        with open(base_path + file, 'r') as f:
            for i in f.readlines():
                i = i.split(' ')  # 按照空格进行划分文件内数值,首字符代表标签类别
                class_dict[classes[int(i[0])]] += 1
    fig, ax = plt.subplots(figsize=(10, 8))
    plt.title('数量')
    plt.xticks(rotation=90)  # x轴文字方向旋转90度
    bars = plt.bar(class_dict.keys(), class_dict.values())
    # 绘制柱形图部分
    for b in bars:
        height = b.get_height()
        ax.annotate(f'{height}',
                    # xy控制的是,标注哪个点,x=x坐标+width/2, y=height,即柱子上平面的中间
                    xy=(b.get_x() + b.get_width() / 2, height),
                    xytext=(0, 3),  # 文本放置的位置,如果有textcoords,则表示是针对xy位置的偏移,否则是图中的固定位置
                    textcoords="offset points",  # 两个选项 'offset pixels','offset pixels'
                    va='bottom', ha='center'  # 代表verticalalignment 和horizontalalignment,控制水平对齐和垂直对齐。
                    )
    plt.savefig('./统计.png',  # ⽂件名:png、jpg、pdf
                dpi=100,  # 保存图⽚像素密度
                bbox_inches='tight')  # 保存图⽚完整
    plt.show()

if __name__ == '__main__':
    # 存放txt文件的路径,末尾的反斜杠不可少
    base_path = r"C:/Users/27801/Desktop/BelgaLogos/txts/"
    main(base_path)

如果你觉得这篇文章对你有所启发的话,期待你的点赞、收藏和打赏,对我创作的支持!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux上使用cmake编译的方法

一、hello 例程仅基于一个cpp文件 C文件或工程进行编译时可以使用g指令(需要对每一个程序和源文件分别使用g指令编译),当程序变大时,一个工程文件往往会包含很文件夹和源文件,这时我们需要的编译指令将越来越长&#…

(vue)el-table-column type=“selection“表格选框怎么根据条件添加禁选

(vue)el-table-column type"selection"表格选框怎么根据条件添加禁选 html <el-table:data"tableData"style"width: 100%"><el-table-columntype"selection"width"55":selectable"checkSelectable">…

linux nginx 安装后,发现SSL模块未安装,如何处理?

&#x1f468;‍⚕ 主页&#xff1a; gis分享者 &#x1f468;‍⚕ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕ 收录于专栏&#xff1a;运维工程师 文章目录 前言SSL模块安装 前言 nginx 安装后&#xff0c;发现SSL模块未安装&…

kubeneters-循序渐进Cilium网络(二)

文章目录 概要IP 地址配置接口配置解析结论 概要 接续前一章节&#xff0c;我们还是以这张图继续深入Cilium网络世界 IP 地址配置 通过检查 Kubernetes 集群的当前环境&#xff0c;可以获取实际的 IP 地址和配置信息。这些信息将被补充到之前的网络示意图中&#xff0c;以使…

虚拟机使用MQ及介绍

mq官网&#xff1a;https://www.rabbitmq.com 一、虚拟机与 MQ 的结合优势 隔离与安全&#xff1a;虚拟机为 MQ 的运行提供了一个独立的环境&#xff0c;与宿主机以及其他虚拟机相互隔离。这意味着即使 MQ 所在的虚拟机出现故障或遭受安全威胁&#xff0c;也不会直接影响到宿主…

比亚迪夏直插家用MPV腹地,“迪王”开启全面销冠新征程

文/王俣祺 导语&#xff1a;比亚迪前脚刚收获2024年的全面成功&#xff0c;后脚立刻就开始布局2025年的产品矩阵了。比亚迪夏的横空出世&#xff0c;看来家用MPV市场也要感受“迪王”的恐怖如斯了。 家用MPV市场的“意外之喜” 1月8日&#xff0c;比亚迪夏终于在万众瞩目之下…

c++入门之 命名空间与输入输出

1、命名空间 1.1使用命名空间的原因 先看一个例子&#xff1a; #include <iostream>int round 0;int main() {printf("%d", round);return 0; }请问&#xff0c;这个程序能跑起来吗&#xff1f; 答案是否定的 原因是&#xff0c;当我们想创建一个全局变量 …

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

12 USART串口通讯

1 串口物理层 两个设备的“DB9接口”之间通过串口信号建立连接&#xff0c;串口信号线中使用“RS232标准”传输数据信号。由于RS232电平标准的信号不能直接被控制器直接识别&#xff0c;所以这些信号会经过“电平转换芯片”转换成控制器能识别的“TTL校准”的电平信号&#xff…

FreePBX 17 on ubuntu24 with Asterisk 20

版本配置&#xff1a; FreePBX 17&#xff08;最新&#xff09; Asterisk 20&#xff08;最新Asterisk 22&#xff0c;但是FreePBX 17最新只支持Asterisk 21&#xff0c;但是21非LTS版本&#xff0c;所以选择Asterisk 20&#xff09; PHP 8.2 Maria DB (v10.11) Node J…

搜广推面经五

饿了么推荐算法 一、介绍InfoNCE Loss、InfoNCE温度系数的作用 InfoNCE Loss&#xff08;Information Noise Contrastive Estimation Loss&#xff09;是一种常用于自监督学习和对比学习中的损失函数&#xff0c;特别是在信息论和无监督学习中有广泛应用。 它的核心思想是通过…

机器学习免费使用的数据集及网站链接

机器学习领域存在许多可以免费使用的数据集&#xff0c;这些数据集来自于学习、研究、比赛等目的。 一、综合性数据集平台 1.Kaggle 网址&#xff1a;Kaggle 数据集https://www.kaggle.com/datasets Kaggle是一个数据科学竞赛和社区平台&#xff0c;提供了大量的数据集供用…

浅尝Appium自动化框架

浅尝Appium自动化框架 Appium自动化框架介绍Appium原理Appium使用安装平台驱动实战 坑 Appium自动化框架介绍 Appium 是一个开源的自动化测试框架&#xff0c;最初设计用于移动应用的测试&#xff0c;但现在它也扩展了对桌面端应用的支持。Appium 使得自动化测试变得更加简单&…

ubuntu 20.04 安装docker--小白学习之路

更新包 sudo apt-get update # 安装需要的软件包以使apt能够通过HTTPS使用仓库 sudo apt-get install ca-certificates curl gnupg lsb-release 使用清华大学源 # 添加Docker官方的GPG密钥 curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo…

MMDetection框架下的常见目标检测与分割模型综述与实践指南

目录 综述与实践指南 SSD (Single Shot MultiBox Detector) 基本配置和使用代码 RetinaNet 基本配置和使用代码 Faster R-CNN 基本配置和使用代码 Mask R-CNN 基本配置和使用代码 Cascade R-CNN 基本配置和使用代码 总结 综述与实践指南 MMDetection是一个基于Py…

语音机器人外呼的缺点

也许是因为经济形式变差&#xff0c;大部分都是消费降级的策略。企业也一样&#xff0c;开源不行就只能重点节流。以前10个人做的工作&#xff0c;希望能用2个语音机器人就能完成。确实语音机器人是可以大幅提升外呼效率的&#xff0c;节约成本也很明显&#xff0c;但是今天不说…

微机原理期末复习(一)

编程题 汇编语言程序的整体结构 STACK SEGMENT STACK STACKDW 100H DUP(?) TOP LABEL WORD ; 使用LEBEL获取栈的尾部偏移地址存储到TOP中&#xff0c;以便初始化sp STACK ENDSDATA SEGMENT... ; 用户定义的变量 DATA ENDSCODE SEGMENTASSUME CS: CODE, DS: DATA, ES: DATA, …

UML(统一建模语言)

目录 一、用例图&#xff08;Use Case Diagram&#xff09; 二、类图&#xff08;Class Diagram&#xff09; 2.1、泛化&#xff08;Generalization&#xff09; 2.2、实现&#xff08;Realization&#xff09; 2.3、关联&#xff08;Association&#xff09; 2.4、聚合&…

流浪猫流浪狗领养PHP网站源码

源码介绍 流浪猫流浪狗领养PHP网站源码&#xff0c;适合做猫狗宠物类的发信息发布。当然其他信息发布也是可以的。 导入数据库&#xff0c;修改数据库配置/application/database.php 设置TP伪静态&#xff0c;设置运行目录&#xff0c; 后台&#xff1a;/abcd.php/dashboard?…

轻量级适合阅读的优秀 C++ 开源项目

CTPL 这是一个现代简易版的、高效的C线程池库&#xff0c;代码行数500行左右。 代码示例&#xff1a; void first(int id) { std::cout << "hello from " << id << \n; } struct Second { void operator()(int id) const { std::cout << &q…