为对象检测任务创建 tfrecord

Posted

技术标签:

【中文标题】为对象检测任务创建 tfrecord【英文标题】:create tfrecord for object detection task 【发布时间】:2018-11-12 21:04:02 【问题描述】:

我正在使用 tensorflow 对象检测 api 为微调任务创建数据集。

我的目录结构是:

火车/

--imgs/

---- img1.jpg

-- 安/

---- img1.csv

每张图片一个 csv 是 label, x, y, w, h

我使用这个脚本来保存 tfrecord:

    import tensorflow as tf
    from os import listdir
    import os
    from os.path import isfile, join
    import csv
    import json

    from object_detection.utils import dataset_util


    flags = tf.app.flags
    flags.DEFINE_string('output_path', '', 'Path to output TFRecord')
    FLAGS = flags.FLAGS

    LABEL_DICT = 
    counter = 0

    def create_tf_example(example):
      # TODO(user): Populate the following variables from your example.
      height = 404 # Image height
      width = 720 # Image width
      filename = example['path'].encode('utf-8').strip() # Filename of the image. Empty if image is not from file

      with tf.gfile.GFile(example['path'], 'rb') as fid:
        encoded_image_data = fid.read()

      image_format = 'jpeg'.encode('utf-8').strip() # b'jpeg' or b'png'

      xmins = [] # List of normalized left x coordinates in bounding box (1 per box)
      xmaxs = [] # List of normalized right x coordinates in bounding box
                 # (1 per box)
      ymins = [] # List of normalized top y coordinates in bounding box (1 per box)
      ymaxs = [] # List of normalized bottom y coordinates in bounding box
                 # (1 per box)
      classes_text = [] # List of string class name of bounding box (1 per box)
      classes = [] # List of integer class id of bounding box (1 per box)

      for box in example['boxes']:
        #if box['occluded'] is False:
        #print("adding box")
        xmins.append(float(int(box['x']) / width))
        xmaxs.append(float(int(box['w']) + int(box['x']) / width))
        ymins.append(float(int(box['y']) / height))
        ymaxs.append(float(int(box['h']) + int(box['y']) / height))
        classes_text.append(box['label'].encode('utf-8'))
        classes.append(int(LABEL_DICT[box['label']]))


      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_image_data),
          '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 ex_info(img_path, ann_path):
      boxes = []
      head = ['label','x','y','w','h']
      with open(ann_path, 'r') as csvfile:
        annreader = csv.DictReader(csvfile, fieldnames=head)
        for box in annreader:
          boxes.append(box)
          LABEL_DICT[box['label']] = LABEL_DICT.get(box['label'], len(LABEL_DICT) + 1)

      ex = 
        "path" : img_path,
        "boxes" : boxes
      

      return ex

    def main(_):
      writer = tf.python_io.TFRecordWriter(FLAGS.output_path)

      # TODO(user): Write code to read in your dataset to examples variable
      dataset_dir = "train"
      ann_dir = join(dataset_dir, "ann")
      imgs_dir = join(dataset_dir, "imgs")
      labelDest = "tfTrain/data/labels_map.pbtxt"

      imgs = [join(imgs_dir, f) for f in listdir(imgs_dir) if isfile(join(imgs_dir, f))]
      anns = [join(ann_dir, os.path.basename(im).replace("jpg","csv")) for im in imgs]

      for img,ann in zip(imgs,anns):
        example = ex_info(img,ann)
        #tf_example = create_tf_example(example)
        #writer.write(tf_example.SerializeToString())


      with open(labelDest, 'w', encoding='utf-8') as outL:
        for name,key in LABEL_DICT.items():
          outL.write("item  \n  id: " + str(key) + "\n  name: '" + name + "'\n\n")


      writer.close()


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

但是当我运行火车脚本时,我得到了这个错误

python train.py --logtostderr --train_dir=./models/train --pipeline_config_path=faster_rcnn_resnet101_coc o.config 警告:张量流:来自模型/研究/object_detection/trainer.py:257:create_global_step (来自 tensorflow.contrib.framewo rk.python.ops.variables) 已弃用,将在未来版本中删除。 更新说明: 请切换到 tf.train.create_global_step 回溯(最近一次通话最后): 文件“models/research/object_detection/utils/label_map_util.py”,第 135 行, 在 load_labelmap text_format.Merge(label_map_string, label_map) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 525 行,在合并中 描述符池=描述符池) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 579 行,在 MergeLines 中 返回 parser.MergeLines(行,消息) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 612 行,在 MergeLines self._ParseOrMerge(行,消息) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 627 行,在 _ParseOrMerge 中 self._MergeField(tokenizer, 消息) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 727 行,在 _MergeField 合并(分词器、消息、字段) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 815 行,在 _MergeMes​​sageField self._MergeField(tokenizer, sub_message) 文件“/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/google/protobuf/text_format.py”, 第 695 行,在 _MergeField (message_descriptor.full_name, name)) google.protobuf.text_format.ParseError:23:20:消息类型“object_detection.protos.StringIntLabelMapItem”没有名为的字段 “s”。

在处理上述异常的过程中,又发生了一个异常:

    Traceback (most recent call last):
      File "train.py", line 184, in <module>
        tf.app.run()
      File "/home/user/anaconda3/envs/tf/lib/python3.6/site-packages/tensorflow/python/platform/app.py",

第 126 行,运行中 _sys.exit(main(argv)) 文件“train.py”,第 180 行,在 main graph_hook_fn=graph_rewriter_fn) 文件“models/research/object_detection/trainer.py”,第 264 行,在 train train_config.prefetch_queue_capacity, data_augmentation_options) 文件“models/research/object_detection/trainer.py”,第 59 行,在 create_input_queue tensor_dict = create_tensor_dict_fn() 文件“train.py”,第 121 行,在 get_next dataset_builder.build(config)).get_next() 文件“models/research/object_detection/builders/dataset_builder.py”,行 155,正在构建中 label_map_proto_file=label_map_proto_file) 文件“模型/研究/object_detection/data_decoders/tf_example_decoder.py”, 第 245 行,在 init 中 使用显示名称) 文件“models/research/object_detection/utils/label_map_util.py”,第 152 行, 在 get_label_map_dict label_map = load_labelmap(label_map_path) 文件“models/research/object_detection/utils/label_map_util.py”,第 137 行, 在 load_labelmap label_map.ParseFromString(label_map_string) TypeError:需要一个类似字节的对象,而不是'str'

我不明白有什么问题。在 tfrecord 中?在里面 标签.pbtxt?还是在配置文件中?

【问题讨论】:

【参考方案1】:

好的,我刚刚解决了调试 tensorflow。结束了我的标签,虽然是 utf-8 格式,但由于一些奇怪的字符,比如 &ù à,tensorflow 不容易读取。从 csv 中删除让火车开始

【讨论】:

以上是关于为对象检测任务创建 tfrecord的主要内容,如果未能解决你的问题,请参考以下文章

如何为对象检测任务创建与 TuriCreate 兼容的 SFrame

『cs231n』图像定位与检测

对象检测/分类任务的性能指标(用于图像)

FreeRTOS 任务栈大小确定及其溢出检测

如何在 Django 模型中使用 celery beat 为每个对象创建单独的任务

如何将使用 Mask Rcnn 在自定义对象检测上创建蒙版图像的 Keras 模型转换为 CoreML 模型以在 iOS 应用程序中使用?