微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

IndexError:子索引超出范围 - 将我的 XML 文件转换为 CSV和 TFRecord 格式

如何解决IndexError:子索引超出范围 - 将我的 XML 文件转换为 CSV和 TFRecord 格式

我正在尝试将我的 XML 文件转换为 CSV。最后,我需要 TFRecord 格式的图像和注释,以使用它们来训练我的自定义 SSD MobileNet V2 320x320 模型。

以下是我用于此过程的完整 python 脚本:

""" Sample TensorFlow XML-to-TFRecord converter

usage: generate_tfrecord.py [-h] [-x XML_DIR] [-l LABELS_PATH] [-o OUTPUT_PATH] [-i IMAGE_DIR] [-c CSV_PATH]

optional arguments:
  -h,--help            show this help message and exit
  -x XML_DIR,--xml_dir XML_DIR
                        Path to the folder where the input .xml files are stored.
  -l LABELS_PATH,--labels_path LABELS_PATH
                        Path to the labels (.pbtxt) file.
  -o OUTPUT_PATH,--output_path OUTPUT_PATH
                        Path of output TFRecord (.record) file.
  -i IMAGE_DIR,--image_dir IMAGE_DIR
                        Path to the folder where the input image files are stored. Defaults to the same directory as XML_DIR.
  -c CSV_PATH,--csv_path CSV_PATH
                        Path of output .csv file. If none provided,then no file will be written.
"""

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

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'    # Suppress TensorFlow logging (1)
import tensorflow.compat.v1 as tf
from PIL import Image
from object_detection.utils import dataset_util,label_map_util
from collections import namedtuple

# Initiate argument parser
parser = argparse.ArgumentParser(
    description="Sample TensorFlow XML-to-TFRecord converter")
parser.add_argument("-x","--xml_dir",help="Path to the folder where the input .xml files are stored.",type=str)
parser.add_argument("-l","--labels_path",help="Path to the labels (.pbtxt) file.",type=str)
parser.add_argument("-o","--output_path",help="Path of output TFRecord (.record) file.",type=str)
parser.add_argument("-i","--image_dir",help="Path to the folder where the input image files are stored. "
                         "Defaults to the same directory as XML_DIR.",type=str,default=None)
parser.add_argument("-c","--csv_path",help="Path of output .csv file. If none provided,then no file will be "
                         "written.",default=None)

args = parser.parse_args()

if args.image_dir is None:
    args.image_dir = args.xml_dir

label_map = label_map_util.load_labelmap(args.labels_path)
label_map_dict = label_map_util.get_label_map_dict(label_map)


def xml_to_csv(path):
    """Iterates through all .xml files (generated by labelImg) in a given directory and combines
    them in a single Pandas dataframe.

    Parameters:
    ----------
    path : str
        The path containing the .xml files
    Returns
    -------
    Pandas DataFrame
        The produced dataframe
    """

    xml_list = []
    for xml_file in glob.glob(path + '/*.xml'):
        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


def class_text_to_int(row_label):
    return label_map_dict[row_label]


def split(df,group):
    data = namedtuple('data',['filename','object'])
    gb = df.groupby(group)
    return [data(filename,gb.get_group(x)) for filename,x in zip(gb.groups.keys(),gb.groups)]


def create_tf_example(group,path):
    with tf.gfile.GFile(os.path.join(path,'{}'.format(group.filename)),'rb') as fid:
        encoded_jpg = fid.read()
    encoded_jpg_io = io.BytesIO(encoded_jpg)
    image = Image.open(encoded_jpg_io)
    width,height = image.size

    filename = group.filename.encode('utf8')
    image_format = b'jpg'
    xmins = []
    xmaxs = []
    ymins = []
    ymaxs = []
    classes_text = []
    classes = []

    for index,row in group.object.iterrows():
        xmins.append(row['xmin'] / width)
        xmaxs.append(row['xmax'] / width)
        ymins.append(row['ymin'] / height)
        ymaxs.append(row['ymax'] / height)
        classes_text.append(row['class'].encode('utf8'))
        classes.append(class_text_to_int(row['class']))

    tf_example = tf.train.Example(features=tf.train.Features(feature={
        'image/height': dataset_util.int64_feature(height),'image/width': dataset_util.int64_feature(width),'image/filename': dataset_util.bytes_feature(filename),'image/source_id': dataset_util.bytes_feature(filename),'image/encoded': dataset_util.bytes_feature(encoded_jpg),'image/format': dataset_util.bytes_feature(image_format),'image/object/bBox/xmin': dataset_util.float_list_feature(xmins),'image/object/bBox/xmax': dataset_util.float_list_feature(xmaxs),'image/object/bBox/ymin': dataset_util.float_list_feature(ymins),'image/object/bBox/ymax': dataset_util.float_list_feature(ymaxs),'image/object/class/text': dataset_util.bytes_list_feature(classes_text),'image/object/class/label': dataset_util.int64_list_feature(classes),}))
    return tf_example


def main(_):

    writer = tf.python_io.TFRecordWriter(args.output_path)
    path = os.path.join(args.image_dir)
    examples = xml_to_csv(args.xml_dir)
    grouped = split(examples,'filename')
    for group in grouped:
        tf_example = create_tf_example(group,path)
        writer.write(tf_example.SerializetoString())
    writer.close()
    print('Successfully created the TFRecord file: {}'.format(args.output_path))
    if args.csv_path is not None:
        examples.to_csv(args.csv_path,index=None)
        print('Successfully created the CSV file: {}'.format(args.csv_path))


if __name__ == '__main__':
    tf.app.run()

以下是我的 XML 文件示例:

<annotation>
    <folder></folder>
    <filename>20210401_135713_jpg.rf.c3433a47627088aa68da9693635476d7.jpg</filename>
    <path>20210401_135713_jpg.rf.c3433a47627088aa68da9693635476d7.jpg</path>
    <source>
        <database>roboflow.ai</database>
    </source>
    <size>
        <width>800</width>
        <height>600</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>orange</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <occluded>0</occluded>
        <bndBox>
            <xmin>167</xmin>
            <xmax>278</xmax>
            <ymin>162</ymin>
            <ymax>264</ymax>
        </bndBox>
    </object>
</annotation>

我收到以下错误

Traceback (most recent call last):
  File "Tensorflow\scripts\generate_tfrecord.py",line 168,in <module>
    tf.app.run()
  File "C:\Users\a\Documents\Capstone\Cuisine_Vision\Detection\cuisinevision\lib\site-packages\tensorflow\python\platform\app.py",line 40,in run
    _run(main=main,argv=argv,flags_parser=_parse_flags_tolerate_undef)
  File "C:\Users\a\Documents\Capstone\Cuisine_Vision\Detection\cuisinevision\lib\site-packages\absl\app.py",line 303,in run
    _run_main(main,args)
  File "C:\Users\a\Documents\Capstone\Cuisine_Vision\Detection\cuisinevision\lib\site-packages\absl\app.py",line 251,in _run_main
    sys.exit(main(argv))
  File "Tensorflow\scripts\generate_tfrecord.py",line 155,in main
    examples = xml_to_csv(args.xml_dir)
  File "Tensorflow\scripts\generate_tfrecord.py",line 88,in xml_to_csv
    int(member[4][0].text),IndexError: child index out of range
Traceback (most recent call last):
  File "Tensorflow\scripts\generate_tfrecord.py",IndexError: child index out of range

有人能想出解决这个问题的办法吗? 谢谢!

解决方法

我认为下面是你要找的

import xml.etree.ElementTree as ET

xml = '''<annotation>
    <folder></folder>
    <filename>20210401_135713_jpg.rf.c3433a47627088aa68da9693635476d7.jpg</filename>
    <path>20210401_135713_jpg.rf.c3433a47627088aa68da9693635476d7.jpg</path>
    <source>
        <database>roboflow.ai</database>
    </source>
    <size>
        <width>800</width>
        <height>600</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>orange</name>
        <pose>Unspecified</pose>
        <truncated>11</truncated>
        <difficult>12</difficult>
        <occluded>13</occluded>
        <bndbox>
            <xmin>167</xmin>
            <xmax>278</xmax>
            <ymin>162</ymin>
            <ymax>264</ymax>
        </bndbox>
    </object>
</annotation>'''

xml_list = []
root = ET.fromstring(xml)
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,member[1].text,int(member[2].text),int(member[3].text),int(member[4].text)
             )
    xml_list.append(value)
print(xml_list)

输出

[('20210401_135713_jpg.rf.c3433a47627088aa68da9693635476d7.jpg',800,600,'orange','Unspecified',11,12,13)]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。