ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Open Images 目标检测推理与评测全流程:TensorFlow Object Detection API 实战指南

Open Images 目标检测推理与评测全流程:TensorFlow Object Detection API 实战指南 Open Images 目标检测推理与评测全流程TensorFlow Object Detection API 实战指南【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/modelsOpen ImagesOID是目前规模最大的带框bounding box目标检测数据集之一包含海量真实场景图片与层级化标签体系。本文以 research/object_detection/g3doc/oid_inference_and_evaluation.md 为主线结合本仓库 TensorFlow Object Detection API 的配套源码完整讲解如何下载 OID validation/test 图片与标注、如何将其打包为 TFRecord、如何加载预训练检测模型跑推理、以及如何用 OID V2 评测协议离线计算 mAP。读完本文你将掌握一套从原始数据集到可复现评测报告metrics.csv的端到端实操方案。---------------------------------------------- | 数据准备阶段约 2 小时内 | ------------ ----------- ---------------- -------------- | OID 标注CSV |-----| create_oid |-----| 图像文件(分片) |-----| TFRecord shard | | 图像文件 | | _tf_record | | | | (100 个分片) | ------------ ----------- ---------------- -------------- | ----------------------------v | 推理阶段 | | infer_detections | | 输入: TFRecord frozen_graph | ---------------------------- | --------------------v | 评测阶段 (offline_eval) | | metrics.csv / mAPIoU≥0.5 | ----------------------------推理输出的检测结果效果示意如下本教程在 OID 数据上得到的典型检测框输出1. 教程范围与资源需求预估本教程完整跑在 Open Images 的validation与test两个评测集上共分四步准备数据标注图片、将数据打包为 TFRecord、加载预训练模型做推理、计算评测指标。官方给出的资源预算如下数据集磁盘空间单卡推理耗时图片数量validation27 GB约 9 小时41,620test75 GB约 27 小时125,436其中“数据下载与打包”等其余步骤在两个集上合计不到 2 小时。时间估算基于单张 NVIDIA Tesla P100 GPU如果你只做快速近似评测可以只处理少数分片见第 5 节「加速推理」从而把时间压缩到分钟级。2. 环境准备本教程沿用 Object Detection API 的标准安装流程核心要点包括安装 TensorFlow 及依赖并确保 Protobuf 库已编译完成、库目录已加入PYTHONPATH——Object Detection API 依赖大量.proto编译产物。pip安装pandas与contextlib2。pandas用于读取 OID 的标注 CSV源码 create_oid_tf_record.py 直接调用pd.read_csvcontextlib2用于多输出文件的优雅关闭ExitStack管理分片 TFRecord 句柄。由于部分数据镜像文件存放在 Google Cloud 存储桶中需要安装 Google Cloud SDK本教程使用gcloud storage rsync下载图片。相关通用安装说明可参见 research/object_detection/g3doc/tf1.md 等页面本教程对应的工具脚本均为 TF1 风格入口运行时需将源码目录research加入PYTHONPATH。3. 准备 Open Images validation/test 数据集3.1 下载标注文件进入tensorflow/models/research即本仓库的根目录下的research/目录创建oid目录并下载标注归档# From tensorflow/models/research mkdir oid cd oid wget https://storage.googleapis.com/openimages/2017_07/annotations_human_bbox_2017_07.tar.gz tar -xvf annotations_human_bbox_2017_07.tar.gz解压后会得到目录2017_07/其中包含train、validation、test三个 split 的annotations-human-bbox.csv人类标注的 bounding box CSV。3.2 下载图片较低分辨率版本本教程使用 CVDF 提供的较低分辨率图片版本镜像统一存放在云存储桶中通过gcloud storage rsync同步# From tensorflow/models/research/oid SPLITvalidation # Set SPLIT to test to download the images in the test set mkdir raw_images_${SPLIT} gcloud storage rsync --recursive gs://open-images-dataset/$SPLIT raw_images_${SPLIT}另一种替代方式直接根据 Open Images 官方「图片 URL 与元数据 CSV」逐张下载得到同样的原始图片目录。下载完成后research/oid目录结构应与下面一致|-- 2017_07 | |-- test | | -- annotations-human-bbox.csv | |-- train | | -- annotations-human-bbox.csv | -- validation | -- annotations-human-bbox.csv |-- raw_images_validation (if you downloaded the validation split) | -- ... (41,620 files matching regex [0-9a-f]{16}.jpg) |-- raw_images_test (if you downloaded the test split) | -- ... (125,436 files matching regex [0-9a-f]{16}.jpg) -- annotations_human_bbox_2017_07.tar.gz注意图片文件名是 16 位小写十六进制字符串形式的ImageID加.jpg后缀这一命名与后面分片打散逻辑直接相关见 3.4。3.3 打包为 TFRecord运行 create_oid_tf_record.py 将标注与图片打包成 TFRecord# From tensorflow/models/research/oid SPLITvalidation # Set SPLIT to test to create TFRecords for the test split mkdir ${SPLIT}_tfrecords PYTHONPATH$PYTHONPATH:$(readlink -f ..) \ python -m object_detection/dataset_tools/create_oid_tf_record \ --input_box_annotations_csv 2017_07/$SPLIT/annotations-human-bbox.csv \ --input_images_directory raw_images_${SPLIT} \ --input_label_map ../object_detection/data/oid_bbox_trainable_label_map.pbtxt \ --output_tf_record_path_prefix ${SPLIT}_tfrecords/$SPLIT.tfrecord \ --num_shards100各命令行参数说明同时对照源码中的 flags 定义Flag含义说明--input_box_annotations_csv框级标注 CSV 路径必填pd.read_csv读入后按ImageID分组--input_images_directory图片像素目录必填脚本按ImageID.jpg查找并读入图片--input_label_maplabel map 文件路径必填本教程用 OID 可训练框类映射 oid_bbox_trainable_label_map.pbtxt其中每项含层级化名称如/m/01g317对应Person、id与display_name--output_tf_record_path_prefix输出路径前缀必填脚本自动追加分片索引与总数--num_shards分片数默认100写出的分片越少每片文件越大--input_image_label_annotations_csv可选图像级标签 CSV指定后会在 TFExample 中额外加入 image-level 标签源码中会将其Confidence列重命名为ConfidenceImageLabel后并入分组需要补充说明两点行为每个图片都会进入输出源码会Glob图片目录下全部*.jpg并把这些ImageID与框标注做并集因此即使某张图没有任何框标注也会被写入 TFRecord可能产生空标注样本。未标注验证信息该转换脚本不向 TFRecord 写入某标签是「正向确认」还是「负向确认」的信息。3.4 分片规则为什么天然支持抽样评测执行后会在oid/${SPLIT}_tfrecords下生成 100 个分片文件文件名形如${SPLIT}.tfrecord-000[0-9][0-9]-of-00100每个分片包含大致相同数量的图片。分片并不是顺序切分而是根据源码中的散列规则shard_idx int(image_id, 16) % FLAGS.num_shards即以图片 ID 的十六进制整数对分片数取模见 create_oid_tf_record.py。由于 ImageID 近似随机分布每个分片在统计上都相当于原始数据的代表性随机子样本。这正是第 5 节「加速推理」中按分片做任务切分、以及在子集上近似计算指标的前提。4. 执行推理推理需要一个训练好的检测模型。本教程使用模型动物园中基于 Open Images 训练的目标检测模型。4.1 下载预训练模型在 模型动物园页model zoo 中可以找到多款 OID 预训练模型的列表与下载链接例如 Faster R-CNN Inception-ResNet v2 Atrous 系列在 OIDv2/v4 上的版本表中同时给出其在 Open Images 评测协议下的 mAPIoU≥0.5。本教程下载其冻结推理图# From tensorflow/models/research/oid wget http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_resnet_v2_atrous_oid_14_10_2017.tar.gz tar -zxvf faster_rcnn_inception_resnet_v2_atrous_oid_14_10_2017.tar.gz解压产物包含frozen_inference_graph.pb等文件后面推理时直接指向该图。4.2 运行 infer_detections数据已打包为 TFRecord、模型已就绪后运行 infer_detections.py# From tensorflow/models/research/oid SPLITvalidation # or test TF_RECORD_FILES$(ls -1 ${SPLIT}_tfrecords/* | tr \n ,) PYTHONPATH$PYTHONPATH:$(readlink -f ..) \ python -m object_detection/inference/infer_detections \ --input_tfrecord_paths$TF_RECORD_FILES \ --output_tfrecord_path${SPLIT}_detections.tfrecord-00000-of-00001 \ --inference_graphfaster_rcnn_inception_resnet_v2_atrous_oid/frozen_inference_graph.pb \ --discard_image_pixelsFlag含义说明--input_tfrecord_paths输入 TFRecord 列表逗号分隔的多文件路径字符串--output_tfrecord_path输出 TFRecord 路径单文件输出命名中00000-of-00001表示“第 0 片共 1 片”--inference_graph推理图路径含权重的冻结图frozen inference graph--discard_image_pixels是否丢弃图像像素布尔默认False置为开启可大幅减小输出体积输出 TFRecord 中每个样本的行为可以从底层 detection_inference.py 得到完整解释输入侧build_input用string_input_producer(shuffleFalse, num_epochs1)逐条读取输入 TFRecord解析其中的image/encoded特征并解码为uint8图像张量shape[1, None, None, 3]图装配build_inference_graph读取.pbGraphDef通过tf.import_graph_def(input_map{image_tensor: image_tensor})把推理图的image_tensor输入连接到解码图像再从默认图中取num_detections、detection_boxes、detection_scores、detection_classes四个输出张量并裁剪到实际检测数量写回infer_detections_and_add_to_example每条输出样例完整保留输入样例的全部原有字段并追加detection_score、detection_bbox_ymin/xmin/ymax/xmax注意转置为 ymin/xmin/ymax/xmax 顺序与detection_class_label若开启--discard_image_pixels则删除image/encoded特征。两点对后续评测非常关键由于 ground truth 框标注字段被一并保留评测只需要推理输出 TFRecord 本身无需再读回图片--discard_image_pixels在评测场景下无损且有显著收益评测指标计算不依赖像素丢掉图片能让输出 TFRecord 体积大幅下降也加快后续读取。兼容性前提该推理脚本要求推理图的输入/输出节点与export_inference_graph.py以--input_typeimage_tensor导出时的语义一致输入为image_tensor输出为上述 detection 张量模型动物园提供的冻结图即满足该约定。5. 加速推理validation/test 图片量巨大41,620 / 125,436 张全量推理耗时长。有三种提速思路可任意组合。5.1 只在少量分片上进行近似评测由于每个分片都是代表性随机子样本可以只挑前若干片快速验证流程TF_RECORD_FILES$(ls ${SPLIT}_tfrecords/${SPLIT}.tfrecord-0000[0-1]-of-00100 | tr \n ,)例如上述命令只处理前 2 个分片即约 2% 的数据。必须注意偏差子集评测会引入方差与偏差——有些类别在子集中几乎不出现导致未出现的类被计为 0 AP 或评估失真。官方给出的实测validation 全集 mAP 为 39.2%而仅前 2 个分片884 张图上 mAP 竟高达 52.4%高约 13.2 个百分点见第 7 节表格可见子集结果与全集差异很大只能用于快速冒烟验证。5.2 多 GPU / 多机并行推理还可以把不同分片分给不同 TensorFlow 设备并行推理。官方脚本用 tmux 为每张 GPU 各开一个infer_detections进程# From tensorflow/models/research/oid SPLITvalidation # or test NUM_GPUS4 NUM_SHARDS100 tmux new-session -d -s inference function tmux_start { tmux new-window -d -n inference:GPU$1 ${*:2}; exec bash; } for gpu_index in $(seq 0 $(($NUM_GPUS-1))); do start_shard$(( $gpu_index * $NUM_SHARDS / $NUM_GPUS )) end_shard$(( ($gpu_index 1) * $NUM_SHARDS / $NUM_GPUS - 1)) TF_RECORD_FILES$(seq -s, -f ${SPLIT}_tfrecords/${SPLIT}.tfrecord-%05.0f-of-$(printf %05d $NUM_SHARDS) $start_shard $end_shard) tmux_start ${gpu_index} \ PYTHONPATH$PYTHONPATH:$(readlink -f ..) CUDA_VISIBLE_DEVICES$gpu_index \ python -m object_detection/inference/infer_detections \ --input_tfrecord_paths$TF_RECORD_FILES \ --output_tfrecord_path${SPLIT}_detections.tfrecord-$(printf %05d $gpu_index)-of-$(printf %05d $NUM_GPUS) \ --inference_graphfaster_rcnn_inception_resnet_v2_atrous_oid/frozen_inference_graph.pb \ --discard_image_pixels done这里用CUDA_VISIBLE_DEVICES为每个进程绑定不同 GPU每进程把分片区间[start_shard, end_shard]对应的 TFRecord 作为输入并输出各自命名的检测文件。所有进程结束后research/oid目录下会出现每个进程一份的输出 TFRecord命名形如validation_detections.tfrecord-0000[0-3]-of-00004。评测阶段用分片通配符4即可一次读取全部 4 份输出见第 6 节。6. 计算评测指标6.1 准备两份配置先创建两个 protobuf 文本配置# From tensorflow/models/research/oid SPLITvalidation # or test NUM_SHARDS1 # Set to NUM_GPUS if using the parallel evaluation script above mkdir -p ${SPLIT}_eval_metrics echo label_map_path: ../object_detection/data/oid_bbox_trainable_label_map.pbtxt tf_record_input_reader: { input_path: ${SPLIT}_detections.tfrecord${NUM_SHARDS} } ${SPLIT}_eval_metrics/${SPLIT}_input_config.pbtxt echo metrics_set: oid_V2_detection_metrics ${SPLIT}_eval_metrics/${SPLIT}_eval_config.pbtxt两份配置文件对应两个 proto 消息InputReader${SPLIT}_input_config.pbtxt描述输入数据位置。其中label_map_path指向 OID 类别映射tf_record_input_reader.input_path支持 shard 通配符N——离线评测脚本会把它展开成${SPLIT}_detections.tfrecord-00000-of-0000N ... ${SPLIT}_detections.tfrecord-N-1-of-0000N一组文件展开规则见 offline_eval_map_corloc.py。因此单机推理产物-00000-of-00001用14 GPU 并行产物-0000[0-3]-of-00004则把NUM_SHARDS设为 GPU 数并用4。EvalConfig${SPLIT}_eval_config.pbtxt描述评测指标核心字段是metrics_set: oid_V2_detection_metricsOID V2 检测指标。6.2 运行离线评测# From tensorflow/models/research/oid SPLITvalidation # or test PYTHONPATH$PYTHONPATH:$(readlink -f ..) \ python -m object_detection/metrics/offline_eval_map_corloc \ --eval_dir${SPLIT}_eval_metrics \ --eval_config_path${SPLIT}_eval_metrics/${SPLIT}_eval_config.pbtxt \ --input_config_path${SPLIT}_eval_metrics/${SPLIT}_input_config.pbtxt从源码看offline_eval_map_corloc.py 的执行链路为用config_util.get_configs_from_multiple_files读取两份配置对每个展开后的输入文件用TfExampleDetectionAndGTParser逐条解析 TFExample同时把 ground truth 与检测结果喂给由metrics_set决定的 evaluatoroid_V2_detection_metrics会创建 OID V2 对应的 evaluator解析失败的样例被跳过并计数最后把各指标以metric_name, value的 CSV 行写入--eval_dir下的metrics.csv。6.3 读取结果metrics.csv运行结束会在${SPLIT}_eval_metrics/metrics.csv生成结果文件。按本教程配置其中包含数据集中每个类别的APIoU≥0.5average precision at IoU ≥ 0.5以及整体的mAPIoU≥0.5。所有 per-class AP 与 mAP 均按 Open Images 官方评测协议 计算语义如下一节所述。7. OID V2 评测协议要点metrics_set: oid_V2_detection_metrics在语义上与 PASCAL VOC 2010 的 mAP 相近先对每类做插值平均精度 AP再对各类取平均得到 mAP但关键差异在于对group-of群体ground-truth 框的处理。Open Images 的annotations-human-bbox.csv中存在两类标注普通框和group-of框框住一大群难以逐一标注个体的框。OID V2 协议据此把每条检测划分为三种情形详见 evaluation_protocols.mdTrue Positive某检测是某个「非 group-of ground-truth 框」在该类上的最高分匹配且两者同类别、IoU 大于阈值默认 0.5Ignored忽略若检测与某group-ofground-truth 框同类别且满足「交叠面积 / 检测面积 0.5」大致落在群体框内则该检测被忽略既不算 TP 也不算 FPFalse Positive既非 TP 也非 Ignored 的检测。Precision / Recall 定义相应为Precision TP 数 / (TP 数 FP 数)Recall TP 数 / 非 group-of 框总数注意落在group-of框上而被忽略的检测不计入 TP因此也不会抬高 recall。此外OID 标签本身是层级化的ground-truth 通常标注到最具体的类例如 car 的两个子类 limousine 与 van其余车类标注为 car。评测软件把各类视为相互独立、忽略层级关系——要让分数达标检测器应输出与之相同的标注粒度。协议文档同时指出旧指标名open_images_V2_detection_metrics已废弃。8. 预期 mAP 参考值使用本教程的模型faster_rcnn_inception_resnet_v2_atrous_oid2017-07 版数据与上述协议官方给出的预期 mAPIoU≥0.5 如下评测集数据比例图片数mAPIoU≥0.5validation全量41,62039.2%validation前 2 个分片88452.4%test全量125,43637.7%test前 2 个分片2,47650.8%这张表同时是「子集近似评测偏差」的最好例证仅前两个分片跑出来的数值系统性偏高因此只有全量结果才适合作为最终论文/报告的指标子集只用于验证流程正确性、调试脚本或做粗糙的快速对照。9. 一次快速上手的推荐路径如果你希望快速复现完整流程而不必等待全量数据建议按下面顺序执行先只下载 validation 前两个分片所需规模的数据或直接全量下载但只转少量分片--num_shards100后可只用*tfrecord-0000[0-1]-of-00100下载冻结模型并跑infer_detections开启--discard_image_pixels按第 6 节生成配置将NUM_SHARDS设为 1运行offline_eval_map_corloc核对metrics.csv输出与第 7 节数量级是否一致验证全链路打通后再扩展到全量或 GPU 并行方案。三个核心入口脚本在仓库中的位置分别为数据集打包脚本 create_oid_tf_record.py、推理脚本 infer_detections.py底层实现见 detection_inference.py、离线评测脚本 offline_eval_map_corloc.pyOID 类别定义见 oid_bbox_trainable_label_map.pbtxt。配合 tf1_detection_zoo.md 中的 OID 预训练模型清单即可把本方案迁移到你自己的检测任务上。【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表