RDD2022 数据格式转换与清洗

这篇具有很好参考价值的文章主要介绍了RDD2022 数据格式转换与清洗。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Rdd2022数据集,是关于道路损伤的数据集,与rdd2020相比增加了两万多张图片
但是由于格式不能被yolo直接使用且其中有大量的图片没有符合要求的标注,特写此文章记录数据清洗与格式化的过程

数据集下载

在开始前需要自己下载zip格式的RDD2022数据集,大小为12.4G 点击此处下载

之后,在桌面上新建一个名为my_file 的文件夹,将上面下载的压缩包放进去,将我的main.py放进去,文件夹结构如下

rdd2020数据集数据格式转化与清洗,日常练习,python,rdd2022,python
在pycharm种运行main文件即可
运行完成后my_file结构如下,其中的my_data就是你要的文件夹,其他的都没用:
rdd2020数据集数据格式转化与清洗,日常练习,python,rdd2022,python

注意事项

注意:

  • 如果运行过程中出现任何bug使得程序没有进行到底,需要删除所有自动生成的文件,回到最开始的目录结构,从新开始运行main文件
  • 如果报错说有缺了什么包,自己去安装即可
  • 注意设置工作目录为你自己新建的那个my_file文件夹,一般情况下默认就是这个,如果报错找不到目录啥的就看下是不是这个问题
  • 按照个人需求,以国家为单位对数据集进行了train:val=7:3的切割
  • 特别注意:代码中将没有任何标注的图片直接剔除了,这可能会对你的训练产生影响

源代码

main.py的代码如下:文章来源地址https://www.toymoban.com/news/detail-740445.html

import zipfile
import os
import os
import xml.etree.ElementTree as ET
from shutil import copyfile
import shutil
import argparse
from pathlib import Path
import random
from collections import defaultdict
import random

work_dir = os.getcwd()
countries = ["China_Drone", "China_MotorBike", "Czech", "India", "Japan", "Norway", "United_States"]
labels = ["D00", "D10", "D20", "D40"]


# 解压最开始的12.4G的压缩包到工作目录
#    解压之后是一个名为 RDD2022_all_countries 的文件夹
def unzip_rdd2022():
    path = os.path.join(work_dir, 'RDD2022.zip')
    zip_file = zipfile.ZipFile(path)
    zip_list = zip_file.namelist()
    for f in zip_list:
        zip_file.extract(f, work_dir)
    zip_file.close()


# RDD2022_all_countries文件夹里面有6个以国家名称命名的压缩包
#    进入这个文件夹里面继续解压,注意是解压到了RDD2022_all_countries
#    这个文件夹里面,至此所有的压缩文件解压完毕
def unzip_RDD2022_all_countries():
    dir_path = os.path.join(work_dir, 'RDD2022_all_countries')
    all_countries_zip_file_name = os.listdir(dir_path)

    for name in all_countries_zip_file_name:
        print('正在解压{}'.format(name))
        all_countries_zip_file_path = os.path.join(dir_path, name)
        zip_file = zipfile.ZipFile(all_countries_zip_file_path)
        zip_list = zip_file.namelist()
        for f in zip_list:
            zip_file.extract(f, dir_path)
        zip_file.close()
        print('{}已解压完成'.format(name))


# 将所有有标签的图片以及对应的标注移动到一个新的文件夹中
#   然后后续操作都是针对这些有标签的图片进行的,其实就是变相去除了
#   没有标签的图片
def remove_useless_file():
    # 一共6个国家,一个国家一个国家的操作
    RDD2022_all_countries_path = os.path.join(work_dir, 'RDD2022_all_countries')
    for country in countries:
        print("开始对 {} 的标签与图片进行操作".format(country))
        annoFiles = os.listdir(os.path.join(RDD2022_all_countries_path, country + "/train/annotations/xmls/"))
        jpgFiles = os.listdir(os.path.join(RDD2022_all_countries_path, country + "/train/images/"))
        newCountry = "new_" + country
        # 在RDD2022_all_countries文件夹下面新建文件夹,new_countryname/Annotations
        #                                          new_countryname/JPEGImages
        annotations_dir = os.path.join(RDD2022_all_countries_path, newCountry, 'Annotations/')
        jpegimages_dir = os.path.join(RDD2022_all_countries_path, newCountry, 'JPEGImages/')
        os.makedirs(annotations_dir, exist_ok=True)
        os.makedirs(jpegimages_dir, exist_ok=True)

        for annoFile in annoFiles:
            tree = ET.parse(
                os.path.join(RDD2022_all_countries_path + "/" + country + "/train/annotations/xmls/", annoFile))
            root = tree.getroot()
            for obj in root.findall("object"):
                a = obj.find("name").text
                if a not in labels:
                    root.remove(obj)

            if len(root.findall("object")) > 0:
                country_path = os.path.join(RDD2022_all_countries_path, country)
                newCountry_path = os.path.join(RDD2022_all_countries_path, newCountry)
                tree.write(newCountry_path + "/Annotations/" + annoFile)
                copyfile(os.path.join(country_path + "/train/images/", annoFile.split(".")[0]) + ".jpg",
                         newCountry_path + "/JPEGImages/" + annoFile.split(".")[0] + ".jpg")
            else:
                # print(f'{annoFile} 没有标签文件')
                continue
        print("{} 的标签与图片操作完毕".format(country))


# 将所有的图片复制到工作目录下的new_train/jpegimages 文件夹下
# 将所有的标签复制到工作目录下的new_train/annotations 文件夹下


def copy_file_2_new_train_dir():
    # 首先创建new_train文件夹
    os.makedirs(work_dir + "new_train/", exist_ok=True)
    # 创建new_train文件夹下面的两个文件夹
    jpeg_path = os.path.join(work_dir, 'new_train', 'jpegimages/')
    annotation_path = os.path.join(work_dir, 'new_train', 'annotations/')
    os.makedirs(jpeg_path, exist_ok=True)
    os.makedirs(annotation_path, exist_ok=True)

    RDD2022_all_countries_path = os.path.join(work_dir, 'RDD2022_all_countries')
    for country in countries:
        print("{}正在复制".format(country))
        jpeg_dir_path = os.path.join(RDD2022_all_countries_path, 'new_' + country, 'JPEGImages')
        all_jpeg_names = os.listdir(jpeg_dir_path)
        annotation_dir_path = os.path.join(RDD2022_all_countries_path, 'new_' + country, 'Annotations')
        all_anno_names = os.listdir(annotation_dir_path)
        for name in all_jpeg_names:
            source = os.path.join(jpeg_dir_path, name)
            target = os.path.join(work_dir, 'new_train', 'jpegimages')
            shutil.copy(source, target)
        for name in all_anno_names:
            source = os.path.join(annotation_dir_path, name)
            target = os.path.join(work_dir, 'new_train', 'annotations')
            shutil.copy(source, target)
        print("{}复制完毕".format(country))


# 生成一个包含所有xml文件路径的txt文件以便 xml2yolo文件调用
def generate_txt_file():
    annoFiles = os.listdir(os.path.join(work_dir, "new_train/Annotations/"))
    yoloFile = open("./xml2yolo_damage.txt", "w")
    for i in range(len(annoFiles)):
        yoloFile.writelines(work_dir + "/new_train/Annotations/" + annoFiles[i] + "\n")
    yoloFile.close()


def xml2yolo():
    import argparse
    import os
    import xml.etree.ElementTree as ET
    from PIL import Image
    from collections import defaultdict

    # Type of image in Dataset
    imageType = ["jpeg", "png", "jpg", "JPEG", "JPG", "PNG"]
    # dictionary to store list of image paths in each class
    imageListDict = defaultdict(set)

    def convert(size, box):
        dw = 1. / size[0]
        dh = 1. / size[1]
        x = (box[0] + box[1]) / 2.0
        y = (box[2] + box[3]) / 2.0
        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]

    # convert minX,minY,maxX,maxY to normalized numbers required by Yolo
    def getYoloNumbers(imagePath, minX, minY, maxX, maxY):
        image = Image.open(imagePath)
        w = int(image.size[0])
        h = int(image.size[1])
        b = (minX, maxX, minY, maxY)
        bb = convert((w, h), b)
        image.close()
        return bb

    def getFileList3(filePath):
        xmlFiles = []
        with open(filePath, "r") as f:
            xmlFiles = f.readlines()
            for i in range(len(xmlFiles)):
                temp = xmlFiles[i].strip().rsplit('.', 1)[0]
                xmlFiles[i] = os.path.abspath(temp.replace("JPEGImages", "Annotations") + ".xml")
                labels_path = os.path.dirname(xmlFiles[i]).replace("Annotations", "labels")
                if not os.path.exists(labels_path):
                    os.mkdir(labels_path)
                assert (os.path.exists(xmlFiles[i]))

        return xmlFiles

    def main():
        parser = argparse.ArgumentParser(description='run phase2.')

        parser.add_argument('--input-file', type=str,
                            help='location to the list of images/xml files(absolute path). sample file at "./xml2yolo_damagee.txt"',
                            default='./xml2yolo_damage.txt')
        args = parser.parse_args()

        # assign each class of dataset to a number
        outputCtoId = {'D00': 0, 'D10': 1, 'D20': 2, 'D40': 3}

        # read the path of the directory where XML and images are present
        xmlFiles = getFileList3(args.input_file)

        print("total files:", len(xmlFiles))
        print('正在转换......')

        # loop over each file under dirPath
        for file in xmlFiles:
            filePath = file
            # print(filePath)
            tree = ET.parse(filePath)
            root = tree.getroot()

            i = 0
            imageFile = filePath[:-4].replace("Annotations", "JPEGImages") + "." + imageType[i]
            while (not os.path.isfile(imageFile) and i < 2):
                i += 1
                imageFile = filePath[:-4].replace("Annotations", "JPEGImages") + "." + imageType[i]

            if not os.path.isfile(imageFile):
                print("File not found:", imageFile)
                continue

            txtFile = filePath[:-4].replace("Annotations", "labels") + ".txt"
            yoloOutput = open(txtFile, "w")

            # loop over each object tag in annotation tag
            for objects in root.findall('object'):
                surfaceType = objects.find('name').text.replace(" ", "")
                if surfaceType == "D30":
                    continue
                bndbox = objects.find('bndbox')
                [minX, minY, maxX, maxY] = [int(float(child.text)) for child in bndbox]
                [x, y, w, h] = getYoloNumbers(imageFile, int(minX), int(minY), int(maxX), int(maxY))
                yoloOutput.write(
                    str(outputCtoId[surfaceType]) + " " + str(x) + " " + str(y) + " " + str(w) + " " + str(h) + "\n")
                imageListDict[outputCtoId[surfaceType]].add(imageFile)
            yoloOutput.close()
        for cl in imageListDict:
            print(labels[cl], ":", len(imageListDict[cl]))

    main()


def generate_my_data():
    # 首先在工作目录下创建 my_data文件夹,以及他下面的images文件夹,labels文件夹
    os.makedirs(work_dir + 'my_data/', exist_ok=True)
    images_path = os.path.join(work_dir, 'my_data', 'images/')
    labels_path = os.path.join(work_dir, 'my_data', 'labels/')
    os.makedirs(images_path, exist_ok=True)
    os.makedirs(labels_path, exist_ok=True)
    # images和labels文件夹下面各有一个train,val文件夹
    os.makedirs(os.path.join(images_path, 'train/'), exist_ok=True)
    os.makedirs(os.path.join(images_path, 'val/'), exist_ok=True)
    os.makedirs(os.path.join(labels_path, 'train/'), exist_ok=True)
    os.makedirs(os.path.join(labels_path, 'val/'), exist_ok=True)
    print("最终my_data文件夹基本结构创建完毕")

    # 将new_train中6个国家的图片的绝对路径分别放到6个列表中
    new_train_path = os.path.join(work_dir, 'new_train')
    jpeg_dir_path = os.path.join(new_train_path, 'jpegimages')
    labels_dir_path = os.path.join(new_train_path, 'labels')
    all_images_name = os.listdir(jpeg_dir_path)

    all_countries_images = defaultdict(lambda: [])
    for name in all_images_name:
        country_name = '_'.join(name.split('_')[:-1])
        all_countries_images[country_name].append(name)
    images_len = sum([len(i) for i in all_countries_images.values()])
    print("一共有{}张图片".format(images_len))
    for k, v in all_countries_images.items():
        print("{} 一共有 {}张图片".format(k, len(v)))
    print('*************************')
    print("开始切分数据集")
    for country in countries:
        image_len = len(all_countries_images[country])
        train_nums = int(image_len * 0.7)
        val_nums = image_len - train_nums
        print("{}一共{}张图片,训练集7/10一共是{}张,测试集3/10一共是{}张,正在切割".format(country, image_len, train_nums, val_nums))
        # 验证集一共val_nums张图片, 一共image_len张图片,索引  0~image_len-1 ,从里面抽取val_index个数
        val_index = random.sample(range(0, image_len), val_nums)
        for idx, name in enumerate(all_countries_images[country]):
            # 图片的复制
            source = os.path.join(jpeg_dir_path, name)
            # target有两种可能,一种是train,一种是val
            target = os.path.join(images_path, 'train') if idx not in val_index else os.path.join(images_path, 'val')
            shutil.copy(source, target)
            # 图片对应的label的复制
            #    label的名称就是图片的名称改掉后缀
            label_name = name.split('.')[0] + '.txt'
            label_source = os.path.join(work_dir, 'new_train', 'labels', label_name)
            label_target = os.path.join(work_dir, 'my_data', 'labels',
                                        'train') if idx not in val_index else os.path.join(work_dir, 'my_data',
                                                                                           'labels', 'val')
            shutil.copy(label_source, label_target)
    all_train_len = len(os.listdir(os.path.join(work_dir, 'my_data', 'images', 'train')))
    all_val_len = len(os.listdir(os.path.join(work_dir, 'my_data', 'images', 'val')))
    print("所有数据切分完毕,训练集一共{}条,验证集一共{}条".format(all_train_len, all_val_len))
    print("\n\n\n\n*************************")
    print("完成,目标文件夹就是my_data, 其他的文件都可以删除")
    print("注意:一共4种损伤类型,4种类型的名称以及对应的编号为")
    for idx, i in enumerate(labels):
        print("{}: {}".format(i, idx))


if __name__ == '__main__':
    print("正在解压12.4G大的最外面的压缩包")
    unzip_rdd2022()
    print("正在解压6个国家的压缩包")
    unzip_RDD2022_all_countries()
    print("对图片进行去除清洗操作")
    remove_useless_file()
    print("正在将所有的图片以及标签复制到统一的目录下")
    copy_file_2_new_train_dir()
    print("正在生成用于标注转换的txt文件")
    generate_txt_file()
    print("正在转换标签")
    xml2yolo()
    print('正在生成最终文件夹')
    generate_my_data()

到了这里,关于RDD2022 数据格式转换与清洗的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Python】PySpark 数据输入 ① ( RDD 简介 | RDD 中的数据存储与计算 | Python 容器数据转 RDD 对象 | 文件文件转 RDD 对象 )

    RDD 英文全称为 \\\" Resilient Distributed Datasets \\\" , 对应中文名称 是 \\\" 弹性分布式数据集 \\\" ; Spark 是用于 处理大规模数据 的 分布式计算引擎 ; RDD 是 Spark 的基本数据单元 , 该 数据结构 是 只读的 , 不可写入更改 ; RDD 对象 是 通过 SparkContext 执行环境入口对象 创建的 ; SparkContext 读取数

    2024年02月14日
    浏览(42)
  • Spark核心RDD详解(设计与运行原理,分区,创建,转换,行动与持久化)

    在实际应用中,存在许多迭代式算法(比如机器学习、图算法等)和交互式数据挖掘工具,这些应用场景的共同之处是,不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。但是,目前的MapReduce框架都是把中间结果写入到HDFS中,带来了大量的

    2024年02月04日
    浏览(46)
  • 【Python】PySpark 数据计算 ③ ( RDD#reduceByKey 函数概念 | RDD#reduceByKey 方法工作流程 | RDD#reduceByKey 语法 | 代码示例 )

    RDD#reduceByKey 方法 是 PySpark 中 提供的计算方法 , 首先 , 对 键值对 KV 类型 RDD 对象 数据 中 相同 键 key 对应的 值 value 进行分组 , 然后 , 按照 开发者 提供的 算子 ( 逻辑 / 函数 ) 进行 聚合操作 ; 上面提到的 键值对 KV 型 的数据 , 指的是 二元元组 , 也就是 RDD 对象中存储的数据是

    2024年02月14日
    浏览(50)
  • 【Python】PySpark 数据计算 ⑤ ( RDD#sortBy方法 - 排序 RDD 中的元素 )

    RDD#sortBy 方法 用于 按照 指定的 键 对 RDD 中的元素进行排序 , 该方法 接受一个 函数 作为 参数 , 该函数从 RDD 中的每个元素提取 排序键 ; 根据 传入 sortBy 方法 的 函数参数 和 其它参数 , 将 RDD 中的元素按 升序 或 降序 进行排序 , 同时还可以指定 新的 RDD 对象的 分区数 ; RDD

    2024年02月14日
    浏览(41)
  • 【Python】PySpark 数据计算 ② ( RDD#flatMap 方法 | RDD#flatMap 语法 | 代码示例 )

    RDD#map 方法 可以 将 RDD 中的数据元素 逐个进行处理 , 处理的逻辑 需要用外部 通过 参数传入 map 函数 ; RDD#flatMap 方法 是 在 RDD#map 方法 的基础上 , 增加了 \\\" 解除嵌套 \\\" 的作用 ; RDD#flatMap 方法 也是 接收一个 函数 作为参数 , 该函数被应用于 RDD 中的每个元素及元素嵌套的子元素

    2024年02月14日
    浏览(36)
  • GEE数据集——2019、2020、2021、2022和2023年全球固定宽带和移动(蜂窝)网络性能Shapefile 格式数据集

    全球固定宽带和移动(蜂窝)网络性能,分配给缩放级别 16 网络墨卡托图块(赤道处约 610.8 米 x 610.8 米)。数据以 Shapefile 格式和 Apache Parquet 格式提供,其几何形状以众所周知的文本 (WKT) 表示,投影在 EPSG:4326 中。下载速度、上传速度和延迟是通过适用于 Android 和 iOS 的 O

    2024年02月05日
    浏览(47)
  • 大数据编程实验:RDD编程

    一、目的与要求 1、熟悉Spark的RDD基本操作及键值对操作; 2、熟悉使用RDD编程解决实际具体问题的方法。 二、实验内容 1 . 给定 数据集 data1.txt,包含了某大学计算机系的成绩,数据格式如下所示: Tom,DataBase,80 Tom,Algorithm,50 Tom,DataStructure,60 Jim,DataBase,90 Jim,Algorithm,60 Jim,DataSt

    2024年04月25日
    浏览(32)
  • Spark RDD编程 文件数据读写

    从本地文件系统读取数据,可以采用textFile()方法,可以为textFile()方法提供一个本地文件或目录地址,如果是一个文件地址,它会加载该文件,如果是一个目录地址,它会加载该目录下的所有文件的数据。 示例:读取一个本地文件word.txt val textFile中的textFile是变量名称,sc.t

    2024年02月05日
    浏览(41)
  • 大数据之RDD的算子分类

    上一篇文章主要讲述了两种RDD的创建方式,本篇文章接着讲RDD的算子及其分类。 RDD的算子主要有两种类型,一种是Transformation转换算子,另一种是Action动作算子,Transformation转换算子执行完成后会返回一个新的RDD,所有的Transformation转换算子都是Lazy,不会立即执行,需要Acti

    2024年02月05日
    浏览(25)
  • 大数据之PySpark的RDD介绍

    之前的文章主要介绍Spark基础知识,例如集群角色、Spark集群运行流程等,接下来会进一步讨论Spark相对核心的知识,让我们拭目以待,同时也期待各位的精彩留言! RDD称为弹性分布式数据集,是Spark中最基本的数据抽象,其为一个不可变、可分区、元素可并行计算的集合;

    2024年02月03日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包