You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用create_coco_tf_record脚本转换COCO标签JSON为TFRecord时遇序列化错误

解决TFRecord写入错误:‘tuple’对象没有‘SerializeToString’属性

这个错误我之前在处理COCO转TFRecord时遇到过,核心问题非常清晰——你传给TFRecordWriter.write()方法的是一个元组(tuple),但TFRecord只接受能调用SerializeToString()的Protobuf对象,比如tf.train.Example或者tf.train.SequenceExample。结合你用create_coco_tf_record类脚本的场景,我来拆解具体原因和解决办法:

可能的错误原因

  • 构造TFExample时返回了元组而非Protobuf对象:你可能在处理图片特征、标注信息时,把多个数据打包成了tuple(比如return (img_feature, bbox_feature)),然后直接把这个tuple传给了writer.write(),而没有封装成标准的tf.train.Example。
  • 未关联COCO的标注数据:你的代码只遍历了label_info["images"],但COCO的标注存在annotations字段里,如果没按image_id匹配标注,后续构造Example时可能生成错误的数据结构(比如tuple)。
  • 代码片段遗漏部分出错:你提供的代码到image["fi..."]中断了,大概率是这里处理图片路径/数据时返回了tuple,导致后续传给writer的不是合法的Example对象。

具体解决方法

1. 确保传给writer的是tf.train.Example实例

必须把图片数据、标注信息(bbox、类别ID、面积等)全部封装成tf.train.Features结构,再构建成tf.train.Example,最后调用它的SerializeToString()方法写入。示例代码如下:

import tensorflow as tf
from collections import defaultdict

def create_coco_tf_example(image_data, image_info, annotations):
    # 提取图片基础信息
    height = image_info["height"]
    width = image_info["width"]
    
    # 整理标注数据
    xmins = []
    xmaxs = []
    ymins = []
    ymaxs = []
    class_ids = []
    
    for ann in annotations:
        # COCO的bbox格式是[x, y, width, height],转成xmin/xmax/ymin/ymax
        x, y, w, h = ann["bbox"]
        xmins.append(x / width)
        xmaxs.append((x + w) / width)
        ymins.append(y / height)
        ymaxs.append((y + h) / height)
        class_ids.append(ann["category_id"])
    
    # 构建Feature字典
    feature_dict = {
        "image/encoded": tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_data])),
        "image/height": tf.train.Feature(int64_list=tf.train.Int64List(value=[height])),
        "image/width": tf.train.Feature(int64_list=tf.train.Int64List(value=[width])),
        "image/object/bbox/xmin": tf.train.Feature(float_list=tf.train.FloatList(value=xmins)),
        "image/object/bbox/xmax": tf.train.Feature(float_list=tf.train.FloatList(value=xmaxs)),
        "image/object/bbox/ymin": tf.train.Feature(float_list=tf.train.FloatList(value=ymins)),
        "image/object/bbox/ymax": tf.train.Feature(float_list=tf.train.FloatList(value=ymaxs)),
        "image/object/class/label": tf.train.Feature(int64_list=tf.train.Int64List(value=class_ids)),
    }
    
    # 返回tf.train.Example对象
    return tf.train.Example(features=tf.train.Features(feature=feature_dict))

# 主流程修改
with open('coco_labels.json') as json_data:
    label_info = json.load(json_data)

# 先把标注按image_id分组,方便后续匹配
annotations_by_image = defaultdict(list)
for ann in label_info["annotations"]:
    annotations_by_image[ann["image_id"]].append(ann)

IMAGE_FOLDER = "coco_images"
with tf.python_io.TFRecordWriter("training.record") as writer:
    for i, image in enumerate(label_info["images"]):
        # 获取对应图片的标注
        image_id = image["id"]
        image_annotations = annotations_by_image.get(image_id, [])
        
        # 读取图片数据(这里建议本地读取,而非requests.get,避免网络问题)
        # 如果你的file_name是URL才用requests,否则用本地路径
        img_data = requests.get(image["file_name"]).content
        # 或者本地读取:img_data = open(os.path.join(IMAGE_FOLDER, image["file_name"]), 'rb').read()
        
        # 生成TFExample并写入
        tf_example = create_coco_tf_example(img_data, image, image_annotations)
        writer.write(tf_example.SerializeToString())

2. 检查所有返回值类型

如果你用了自定义函数处理数据,一定要确认函数返回的是tf.train.Example,而不是tuple或其他类型。比如不要写出return (img_data, annotations)这种代码,必须把这些数据封装成Protobuf对象后返回。

3. 修复图片数据读取逻辑

如果你的image["file_name"]是本地路径,建议用open()本地读取而非requests.get(),避免网络请求返回异常数据(比如tuple)。如果是URL,也要确保requests.get(image["file_name"]).content返回的是字节流,而非其他结构。

内容的提问来源于stack exchange,提问作者Oblomov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:51:44