TensorFlow Models / DELF 地标检测快速上手:用预训练 Faster-RCNN 检测器在 Oxford 数据集上定位地标
本文是 TensorFlow Model Garden 中 DELF(Deep Local and Global Image Features)项目的地标检测(landmark detection)实践指南。它以仓库中的 DETECTION.md 为主干,讲解如何安装 DELF 库、准备 Oxford 建筑图像、下载在 Google Landmark Boxes 上预训练的检测器,并借助 extract_boxes.py 一键完成地标区域检测与可视化。读完本文,你将能够在自己的图像清单上运行基于 Faster-RCNN 或 MobileNet-SSD 的检测模型,输出归一化坐标的检测框文件(.boxes),并生成带框标注的 _viz.jpg 预览图,为后续的 DELF 特征提取、区域聚合检索(Detect-to-Retrieve)等任务打好前置准备。
一、地标检测在 DELF 生态中的位置
从 research/delf/README.md 可知,DELF 项目围绕四篇论文的研究成果构建代码:DELF(ICCV'17)、Detect-to-Retrieve(CVPR'19)、DELG(ECCV'20)以及 Google Landmarks Dataset v2(CVPR'20)。其中**检测(detection)**是 Detect-to-Retrieve 方法的基础环节——先用目标检测模型在查询图像中定位"地标"出现的区域,再针对这些区域做局部/全局特征提取与聚合,从而提升实例级识别与图像检索的效果。
该项目发布了两个在 Google Landmark Boxes 数据集上预训练的检测器模型(见 README 的 Pre-trained models 小节):
- Faster-RCNN 检测器:下载包为
d2r_frcnn_20190411.tar.gz,这是 DETECTION.md 默认使用的模型; - MobileNet-SSD 检测器:下载包为
d2r_mnetssd_20190411.tar.gz,更轻量,README 中说明两者的使用指令完全通用,可无缝切换。
DETECTION.md 描述的就是"快速开始(Quick start):地标检测"——它是一个端到端的最小可运行示例:用两张来自 Oxford buildings 数据集的图片,验证上述检测器能输出高质量的地标框。
二、环境准备:安装 DELF 库
要运行本示例,首先需要正确安装 DELF 库。仓库中的 research/delf/INSTALL_INSTRUCTIONS.md 提供了两种方式。
2.1 一键安装脚本
官方推荐在 64 位 Linux 上使用一键脚本:
# From models/research/delf/delf/python/training
bash install_delf.sh
脚本依次完成:安装 TensorFlow 2.2(CPU/GPU)、从源码安装 TF-Slim、下载 protoc 并编译 DELF 的 Protocol Buffers、安装 matplotlib/numpy/scikit-image/scipy/python3-tk、安装 TensorFlow Object Detection API、最后安装 DELF 包。
2.2 手工分步安装
如果不方便运行脚本,也可按下列步骤手工安装(均以 research/delf 目录为工作起点):
# 1) TensorFlow(Python 3.6+)
pip3 install 'tensorflow>=2.2.0' # GPU: tensorflow-gpu>=2.2.0
# 2) TF-Slim 需从源码安装(避免旧版本依赖已废弃的 tf.contrib)
git clone git@github.com:google-research/tf-slim.git
cd tf-slim && pip3 install .
# 3) 下载 protoc(>= 3.3),然后编译 DELF 的 proto 文件
# 从 research/delf/ 目录执行:
${PATH_TO_PROTOC?}/bin/protoc delf/protos/*.proto --python_out=.
# 4) Python 依赖
pip3 install matplotlib numpy scikit-image scipy
sudo apt-get install python3-tk
# 5) 安装 DELF 包(若权限不足可加 sudo,必要时去掉 -e)
pip3 install -e . # 在 research/delf/ 目录下执行
安装完成后,用如下命令自检:
python3 -c 'import delf'
若没有报错即表示 DELF 包加载成功。DELF 的 proto 位于 research/delf/delf/protos,其中 box.proto 负责检测框的序列化格式、delf_config.proto 负责特征提取配置,均为编译依赖项。
三、准备图像:下载 Oxford 建筑数据集并生成检测清单
为了演示检测器用法,DETECTION.md 建议下载 Oxford buildings dataset。下载与解压的具体指令在 research/delf/EXTRACTION_MATCHING.md 的 "Download Oxford buildings dataset" 小节中给出:把数据集解压到 delf/python/examples/data/oxford5k_images/ 目录下即可。
随后,在示例目录 delf/python/examples/ 中创建检测图像清单 list_images_detector.txt,每一行写一个图像路径:
# From tensorflow/models/research/delf/delf/python/examples/
echo data/oxford5k_images/all_souls_000002.jpg >> list_images_detector.txt
echo data/oxford5k_images/all_souls_000035.jpg >> list_images_detector.txt
从源码看,该清单的解析逻辑位于 extract_boxes.py 的 _ReadImageList():它逐行读取文件并去除行尾空白,因此每行一个图像路径是最基本的格式要求;同时脚本顶部 docstring 明确说明"图像必须为 JPG 格式"。这份清单与 DELF 特征提取阶段使用的 list_images.txt(对应 EXTRACTION_MATCHING.md 中的示例)结构完全一致,方便后续将检测与特征提取串联成流水线。
四、下载预训练检测模型
接着下载 Faster-RCNN 检测器模型到 parameters/ 目录:
# From tensorflow/models/research/delf/delf/python/examples/
mkdir parameters && cd parameters
wget http://storage.googleapis.com/delf/d2r_frcnn_20190411.tar.gz
tar -xvzf d2r_frcnn_20190411.tar.gz
cd ..
下载并解压后得到的是一个导出的 SavedModel 目录(例如 d2r_frcnn_20190411/),这正是 detector.py 中 MakeDetector(model_dir) 通过 tf.saved_model.load(model_dir) 加载的对象。
说明:DETECTION.md 特别注明,上述为 Faster-RCNN 版本;项目还同时发布 MobileNet-SSD 版本(
d2r_mnetssd_20190411.tar.gz),下载链接见 README 的 Pre-trained models 小节。两种模型在下面的指令中均可无缝使用——只需把--detector_path指向对应的解压目录。
五、运行检测命令:extract_boxes.py 的参数与输出
一切就绪后,在 delf/python/examples/ 目录执行以下命令,即会以 0.8 的置信度阈值对两张 all_souls 图像检测地标框,并输出可视化结果:
# From tensorflow/models/research/delf/delf/python/examples/
python3 extract_boxes.py \
--detector_path parameters/d2r_frcnn_20190411 \
--detector_thresh 0.8 \
--list_images_path list_images_detector.txt \
--output_dir data/oxford5k_boxes \
--output_viz_dir data/oxford5k_boxes_viz
5.1 命令行参数详解
对照 extract_boxes.py 底部的 argparse 定义,各参数的含义与默认值如下:
| 参数 | 默认值 | 含义(依据源码注释) |
|---|---|---|
--detector_path |
/tmp/d2r_frcnn_20190411/ |
导出的检测模型(SavedModel)路径 |
--detector_thresh |
0.0 |
检测阈值,置信度得分低于该值的框不会被返回 |
--list_images_path |
list_images.txt |
待检测图像清单文件路径,每行一个图像 |
--output_dir |
test_boxes |
检测框输出目录;每张图像一个 .boxes 文件(同名、扩展名替换) |
--output_viz_dir |
''(空) |
可选;若设置,则生成"检测框叠加在图像上"的可视化并保存,文件名带 _viz.jpg 后缀 |
本示例把阈值设为 0.8,意味着只保留检测置信度 不低于 0.8 的框;实际使用时可根据精度/召回需求调低(如默认 0.0 则保留全部框)。输出时,程序会把 .boxes 框文件写入 data/oxford5k_boxes,把可视化图片写入 data/oxford5k_boxes_viz。
5.2 预期输出效果
运行结束后,data/oxford5k_boxes_viz 目录下会生成两张可视化图片,其效果与仓库中随附的示例结果一致——红色矩形框清晰地覆盖了画面中的地标建筑主体区域:
六、源码级原理:检测主流程拆解
理解示例的运行机制,有助于把检测步骤平滑嵌入你自己的检索/识别流程。核心代码集中在两个文件中:extract_boxes.py(主流程)与 detector.py(模型封装)。
6.1 模型加载与张量剪枝
detector.py 中的 MakeDetector() 把导出的 SavedModel 剪枝为一个"输入—输出"最小接口:
model = tf.saved_model.load(model_dir)
feeds = ['input_images:0']
fetches = ['detection_boxes:0', 'detection_scores:0', 'detection_classes:0']
model = model.prune(feeds=feeds, fetches=fetches)
即模型的输入张量是 input_images:0(uint8 的 RGB 批图像,形状为 (batch, height, width, 3)),返回三个输出:detection_boxes、detection_scores 与 detection_classes。由此可以推断:DELF 项目发布的预训练检测器统一遵循这一张量命名约定,extract_boxes.py 无需关心具体是 Faster-RCNN 还是 MobileNet-SSD,这正是"两种模型指令无缝通用"的底层原因。
6.2 主循环:过滤、落盘与可视化
extract_boxes.py 的 main() 按如下流程工作:
- 读取图像清单,统计待处理数量,并创建
--output_dir/--output_viz_dir(若未存在); - 通过
detector.MakeDetector(cmd_args.detector_path)构造检测函数detector_fn; - 逐张图像处理:用
utils.RgbLoader()读图并扩展为 batch 维度后送入detector_fn,得到(boxes, scores, class_indices); - 调用
_FilterBoxesByScore(),仅保留scores[i] >= detector_thresh的框及其得分、类别索引; - 用
box_io.WriteToFile()把筛选结果写入.boxes文件;若设置了--output_viz_dir,再调用_PlotBoxesAndSaveImage()叠加绘制红色(循环色r/y/b/m/k/g/c/w)矩形框并保存为_viz.jpg; - 每处理 100 张图像打印一次进度日志,便于在超大数据集上观察运行状态。
值得注意的两个工程细节:
- 断点续跑:程序在处理每张图前会检查对应
.boxes文件是否已存在,存在则打印Skipping ...并跳过。这在批量检测时非常实用——中断后重跑不会重复计算已完成的图像; - 归一化坐标:检测器输出的框坐标是归一化后的
[top, left, bottom, right](即[ymin, xmin, ymax, xmax],取值约在[0,1])。可视化时_PlotBoxesAndSaveImage()需要将归一化坐标乘上图像的实际高、宽(scaled_box = [box[0]*height, box[1]*width, ...])才能正确落位。
6.3 .boxes 输出文件格式:box.proto 与 box_io
检测框文件的格式由 box.proto 定义:一个 Boxes 消息包含多个 Box,每个 Box 有 6 个字段:
| 字段 | 说明 |
|---|---|
ymin / xmin / ymax / xmax |
归一化框坐标,对应 [top, left, bottom, right] |
score |
检测得分,通常越高越可信 |
class_index |
框对应的类别索引 |
读写接口位于 box_io.py:WriteToFile() 把 numpy 数组(boxes: [N,4]、scores: [N]、class_indices: [N])序列化为 Boxes proto 二进制写入文件,ReadFromFile() 则执行反向解析;两者均基于 tf.io.gfile,因此天然支持远端存储路径。这份 .boxes 输出正是后续 Detect-to-Retrieve 阶段"对检测区域提取局部特征"的输入,相关聚合、索引与检索脚本的说明可见 README 的代码总览中对 delf/python/detect_to_retrieve 子目录的介绍。
七、常见问题排查
matplotlib 无显示环境报错
在无图形界面的服务器(如纯 SSH 环境)上运行时,matplotlib 可能报出类似 no display name and no $DISPLAY environment variable 的错误。DETECTION.md 给出的解决方案是:在 ~/.config/matplotlib/matplotlibrc 文件中加入一行,强制使用非交互后端:
backend : Agg
这样 plt.savefig() 即可在无显示器的情况下正常把可视化图片落盘。
其他依赖提示
DELF 特征提取/匹配流程还可能遇到 scikit-image 相关异常,EXTRACTION_MATCHING.md 提到可用 pip3 install -U scikit-image 升级到 0.14.1 以上版本解决;若 pip3 install -e . 出现安装问题,可尝试去掉 -e 选项或为命令添加 sudo(详见 INSTALL_INSTRUCTIONS.md 的 Troubleshooting 小节)。
八、下一步:把检测接入检索流水线
完成上述检测后,你已得到每张图像的地标框(.boxes)。在 DELF 的整体思路中,这通常只是第一步:后续可以按照 EXTRACTION_MATCHING.md 对框内区域提取 DELF 局部特征并进行图像匹配,或者参考 README 中关于 DELG、Detect-to-Retrieve、GLDv2 baseline 的指引,使用同一批检测框参与区域特征聚合、建库检索与重排,从而把"定位地标"升级为完整的实例级识别与检索系统。文中展示的 extract_boxes.py 支持任意数量的 JPG 图像清单、支持阈值调节与断点续跑,可作为你自定义检测数据集的起点工具。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

