【制作数据集时,用python脚本对标注信息进行数据清洗和可视化】

文前白话

使用labelimg标注工具对图片进行标注后,为了防止标注的信息有误,或者标注类别不准确,会影响训练的正常进行,有必要进行标注信息的清洗与核查。进行数据清洗步骤之前,将标注的好的xml文件和数据原图分别存放在不同的文件夹中。

在这里插入图片描述

Ⅰ、涉及的脚本代码

Step1: 检查所标注的xml文件中是否有命名不合规范的存在

脚本代码:


# 代码描述:数据清洗第一步--- 检查所标注的xml文件中是否有命名不合规范的存在
#  
# 创建时间: 2021-01-08
# 创建人: Kenn Wu
# 修改时间:
# 版本:

import os
from tqdm import tqdm

xml_path = 'E:/Desktop/dataset/Vehicle/xml/'       # 标注文件路径
image_path = 'E:/Desktop/dataset/Vehicle/jpg/'     # 数据原图路径
image_lst = os.listdir(image_path)
xml_lst = os.listdir(xml_path)
print("image list:", len(image_lst))
print("xml list:", len(xml_lst))

for xml in xml_lst:
    if len(xml) != 10:
        print(xml)

效果:

在这里插入图片描述

Step2: 对比数据源图(jpg)与所保存的标注的xml文件,打印缺失的xml图片序号

脚本代码:


# 代码描述:数据清洗第二步--- 对比数据源图(jpg)与所保存的标注的xml文件,打印缺失的xml图片序号
#  
# 创建时间: 2021-01-08
# 创建人: Kenn Wu
# 修改时间:
# 版本:

import os
from tqdm import tqdm

xml_path = 'E:/Desktop/dataset/Vehicle/xml/'       # 标注文件路径
image_path = 'E:/Desktop/dataset/Vehicle/jpg/'     # 数据原图路径
image_lst = os.listdir(image_path)
xml_lst = os.listdir(xml_path)
print("image list:", len(image_lst))
print("xml list:", len(xml_lst))

missing_index = []
for image in tqdm(image_lst):
    xml = image[:-4] + '.xml'
    if xml not in xml_lst:
        missing_index.append(xml[:-4])
print(len(missing_index))
print(missing_index)

效果:

在这里插入图片描述

Step3: 删除没有对应xml文件的jpg文件

脚本代码:


# 代码描述:数据清洗第三步--- 删除没有对应xml文件的jpg文件
#  
# 创建时间: 2021-01-08
# 创建人: Kenn Wu
# 修改时间:
# 版本:

import os
from tqdm import tqdm

xml_path = 'E:/Desktop/dataset/Vehicle/xml/'       # 标注文件路径
image_path = 'E:/Desktop/dataset/Vehicle/jpg/'     # 数据原图路径

image_lst = os.listdir(image_path)
xml_lst = os.listdir(xml_path)

missing_index = []
for image in tqdm(image_lst):
    xml = image[:-4] + '.xml'
    if xml not in xml_lst:
        missing_index.append(xml[:-4])

for index in missing_index:
    image = index + '.jpg'
    os.remove(image_path + image)
    

Step4: 将标注的所有xml文件信息写入一个excel表格,后期数据分析使用

脚本代码:


# 代码描述:数据清洗第四步--- 将所有xml文件信息写入一个excel表格,后期数据分析使用
#  
# 创建时间: 2021-01-08
# 创建人: Kenn Wu
# 修改时间:
# 版本:

import os
import glob
import pandas as pd
import xml.etree.ElementTree as ET

def xml_to_csv(path):
    xml_list = []
    for xml_file in glob.glob(path + '*.xml'):
        print(xml_file)
        tree = ET.parse(xml_file)
        root = tree.getroot()
        for member in root.findall('object'):
            value = (root.find('filename').text,
                     int(root.find('size')[0].text),
                     int(root.find('size')[1].text),
                     member[0].text,
                     int(member[4][0].text),
                     int(member[4][1].text),
                     int(member[4][2].text),
                     int(member[4][3].text)
                     )
            xml_list.append(value)
    column_name = ['filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax']
    xml_df = pd.DataFrame(xml_list, columns=column_name)
    return xml_df

if __name__ == "__main__":
    xml_path = 'E:/Desktop/dataset/Vehicle/xml/'       # 标注文件路径
    xml_df = xml_to_csv(xml_path)
    xml_df.to_csv('dataset_Vehicle.csv', index=None)
    print('Successfully converted xml to csv.')
    

效果:

在这里插入图片描述
在这里插入图片描述

Step5: 数据分析,查看xml文件统计信息,生成网页数据报告


# 代码描述:数据清洗第五步--- 数据分析,查看xml文件统计信息,生成数据报告
#  
# 创建时间: 2021-01-08
# 创建人: Kenn Wu
# 修改时间:
# 版本:

import pandas_profiling
import pandas as pd

def eda(in_file, out_file):
    data = pd.read_csv(in_file, sep=',')
    pfr = pandas_profiling.ProfileReport(data)
    pfr.to_file(out_file)


if __name__ == '__main__':
    in_file = 'dataset_Vehicle.csv.csv'
    out_file = 'dataset_Vehicle.csv.html'
    eda(in_file, out_file)
    print('eda done!')

运行效果:

在这里插入图片描述
在浏览器中打开,可以查看生成的报告:

在这里插入图片描述

在这里插入图片描述

如果有错误标注:

Step6: 改写 label 标错的xml文件


# 代码描述:数据清洗第六步--- 改写标注时候 label 标错的xml文件
#  
# 创建时间: 2021-01-08
# 创建人: Kenn Wu
# 修改时间:
# 版本:

import glob
import xml.etree.ElementTree as ET


def main(path):
    wrong_class_lst1, wrong_class_lst2, w_lst = [], [], []
    for xml_file in glob.glob(path + '*.xml'):
        print(xml_file)
        tree = ET.parse(xml_file)
        root = tree.getroot()

        for member in root.findall('object'):
            value = member[0].text
            if value == 'chemical_vehical' or value == 'chemcial_vehicle' or value == 'chemical_vehicel':
                wrong_class_lst1.append(root.find('filename').text)
                member[0].text = 'chemical_vehicle'
            if value == 'chemical_sigh':
                wrong_class_lst2.append(root.find('filename').text)
                member[0].text = 'chemical_sign'
            if value == 'w':
                w_lst.append(root.find('filename').text)
        tree.write(xml_file)
    print('wrong_class_list1:', wrong_class_lst1)
    print('wrong_class_list2:', wrong_class_lst1)
    print('w_list:', w_lst)


if __name__ == "__main__":
    xml_path = 'E:/Desktop/dataset/Vehicle/xml/'
    main(xml_path)

Ⅱ、实际操作补充

实际操作的时候,可以把这6个脚本文件放在同一个文件夹中,设置好相应的文件路径,依次进行即可。当然,喜欢省事又不介意动手的小伙伴,不妨进行合并,在一个脚本中利用函数的调用实现整体的功能!

在这里插入图片描述

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值