【发布时间】:2018-10-03 19:41:10
【问题描述】:
我想读取存储在 TFRecord 文件中的数据,该文件已用作TF Object Detection API 中的火车记录。
但是,我收到了InvalidArgumentError: Input to reshape is a tensor with 91090 values, but the requested shape has 921600。我不明白错误的根源是什么,即使差异似乎是 10 倍。
问题: 如何读取文件而不出现此错误?
- 我不能排除错误来自创建记录,或者错误在于我阅读记录的方式。因此,我已经包含了我的代码。
- 我能够使用数据运行 object_detection/train.py,并从经过训练的模型生成冻结图。
- 从 this answer(以及它提到的 GitHub 问题)中,我发现我必须将我的 PNG 图像转换为 JPG,因此需要
as_jpg-part(请参阅下面的代码)。 - 我使用this answer 中的代码作为读取文件的起点。
- 我使用 TensorFlow 1.7.0、Python 3.5
只有一个类:“人类”。 记录有 1000 张图像;每个图像可以有一个或多个边界框。 (对应图像中的每个人一个。)
我如何阅读 TFRecord: 如上所述:我使用this answer的代码作为读取文件的起点:
train_record = 'train.record'
def read_and_decode(filename_queue):
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(
serialized_example,
# Defaults are not specified since both keys are required.
features={
'image/height': tf.FixedLenFeature([], tf.int64),
'image/width': tf.FixedLenFeature([], tf.int64),
'image/source_id': tf.FixedLenFeature([], tf.string),
'image/encoded': tf.FixedLenFeature([], tf.string),
'image/format': tf.FixedLenFeature([], tf.string),
'image/object/bbox/xmin': tf.VarLenFeature(tf.float32),
'image/object/bbox/xmax': tf.VarLenFeature(tf.float32),
'image/object/bbox/ymin': tf.VarLenFeature(tf.float32),
'image/object/bbox/ymax': tf.VarLenFeature(tf.float32),
'image/object/class/text': tf.VarLenFeature(tf.string),
'image/object/class/label': tf.VarLenFeature(tf.int64)
})
image = tf.decode_raw(features['image/encoded'], tf.uint8)
# label = tf.cast(features['image/object/class/label'], tf.int32)
height = tf.cast(features['image/height'], tf.int32)
width = tf.cast(features['image/width'], tf.int32)
return image, height, width
def get_all_records(FILE):
with tf.Session() as sess:
filename_queue = tf.train.string_input_producer([ FILE ])
image, height, width = read_and_decode(filename_queue)
image = tf.reshape(image, tf.stack([height, width, 3]))
image.set_shape([640,480,3])
init_op = tf.initialize_all_variables()
sess.run(init_op)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for i in range(1):
example, l = sess.run([image])
img = Image.fromarray(example, 'RGB')
img.save( "output/" + str(i) + '-train.png')
print (example,l)
coord.request_stop()
coord.join(threads)
get_all_records(train_record)
创作:
我创建了一个类 Image 来对图像进行逻辑建模,并创建了一个类 Rect 来表示边界框和标签。这不是很相关,但是下面的代码在看到变量img 或rect 时会使用它们。
一个相关的部分可能是get_bytes()-方法,它更像是使用PIL的Image.open(file_path)的包装器:
class Image:
# ... rest of class
def open_img(self):
if self.file_path is not None:
return Image.open(self.file_path)
def get_bytes(self, as_jpg=False):
if self.file_path is None:
return None
if as_jpg:
# Convert to jpg:
with BytesIO() as f:
self.open_img().convert('RGB').save(f, format='JPEG', quality=95)
return f.getvalue()
else: # Assume png
return np.array(self.open_img().convert('RGB')).tobytes()
我如何创建示例:
use_jpg = True
def create_tf_example(img):
image_format= b'jpg' if use_jpg else b'png'
encoded_image_data = img.get_bytes(as_jpg=use_jpg) # Encoded image bytes
relative_path = img.get_file_path()
if relative_path is None or not img.has_person():
return None # Ignore images without humans or image data
else:
filename = str(Path(relative_path).resolve()) # Absolute filename of the image. Empty if image is not from file
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 rect in img.rects:
if not rect.is_person:
continue # For now, ignore negative samples as TF does this by default
else:
xmin, xmax, ymin, ymax = rect.get_normalized_xy_min_max()
xmins.append(xmin)
xmaxs.append(xmax)
ymins.append(ymin)
ymaxs.append(ymax)
# Human class:
classes.append(1)
classes_text.append('Human'.encode())
return 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.encode()),
'image/source_id': dataset_util.bytes_feature(filename.encode()),
'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),
}))
我如何创建 TFRecord:
def convert_to_tfrecord(imgs, output_file_path):
with tf.python_io.TFRecordWriter(output_file_path) as writer:
for img in imgs:
tf_example = create_tf_example(img)
if tf_example is not None:
writer.write(tf_example.SerializeToString())
convert_to_tfrecord(train_imgs, 'train.record')
convert_to_tfrecord(validation_imgs, 'validate.record')
convert_to_tfrecord(test_imgs, 'test.record')
来自dataset_util 模块:
def int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def int64_list_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
def bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def bytes_list_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))
def float_list_feature(value):
return tf.train.Feature(float_list=tf.train.FloatList(value=value))
【问题讨论】:
标签: python tensorflow object-detection-api tfrecord