首页
/ DELF 快速上手:基于 TensorFlow Models 的局部特征提取与图像匹配完整教程

DELF 快速上手:基于 TensorFlow Models 的局部特征提取与图像匹配完整教程

2026-09-06 18:16:12作者:田桥桑Industrious

DELF(DEep Local Features)是 Google 提出的带注意力机制的深度局部特征方法,用于实例级识别与图像检索场景下的关键点定位与描述子匹配。本文以 TensorFlow Models 仓库 research/delf/EXTRACTION_MATCHING.md 为主线,完整演示从环境安装、Oxford 建筑物数据集下载、预训练模型加载,到调用 extract_features.py 提取 .delf 特征、再经 match_images.py 完成最近邻匹配与 RANSAC 几何校验的端到端流程。读完本文,你将能够独立跑通一次 DELF 特征提取与两两图像匹配,并理解每一步背后对应的源码实现与配置含义。

一、准备工作:安装 DELF 库

DELF 代码依赖 TensorFlow、TF-Slim、protobuf、protoc 编译器及若干 Python 库。仓库提供了两种安装路径:

方式一:一键脚本安装(推荐)

进入 models/research/delf/delf/python/training 目录,直接运行:

# From models/research/delf/delf/python/training
bash install_delf.sh

该脚本(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 包。需要说明的是,脚本只适用于 64 位 Linux,因为其中会自动下载与架构绑定的 protoc 二进制;其他架构需参照脚本中注释手动替换 protoc 的下载版本。

方式二:手工分步安装

若一键脚本失败,可参考 INSTALL_INSTRUCTIONS.md 逐步安装,核心步骤为:

# 1. TensorFlow(需 2.2 及以上)
pip3 install 'tensorflow>=2.2.0'        # CPU
# pip3 install 'tensorflow-gpu>=2.2.0'  # GPU

# 2. 从源码安装 TF-Slim(避免旧版依赖已废弃的 tf.contrib)
git clone git@github.com:google-research/tf-slim.git
cd tf-slim && pip3 install .

# 3. Python 依赖
pip3 install matplotlib numpy scikit-image scipy
sudo apt-get install python3-tk

# 4. 将 tensorflow/models 加入 PYTHONPATH(Object Detection API 需要)
# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:`pwd`

# 5. 编译 DELF protobuf(PATH_TO_PROTOC 为 protoc 下载目录,版本需 >= 3.3)
# From tensorflow/models/research/delf/
${PATH_TO_PROTOC?}/bin/protoc delf/protos/*.proto --python_out=.

# 6. 安装 delf 包
# From tensorflow/models/research/delf/
pip3 install -e .

安装完成后,执行 python3 -c 'import delf' 无报错即表示 DELF 包加载成功。若 pip3 install -e(editable 模式)报错,可去掉 -e;权限不足时在前面加 sudo

二、下载 Oxford 建筑物数据集

本教程使用经典的 Oxford Buildings(Oxford5k) 数据集来演示。为与后续命令保持一致,请将数据解压到 models/research/delf/delf/python/examples 目录下:

# From tensorflow/models/research/delf/delf/python/examples/
mkdir data && cd data
wget http://www.robots.ox.ac.uk/~vgg/data/oxbuildings/oxbuild_images.tgz
mkdir oxford5k_images oxford5k_features
tar -xvzf oxbuild_images.tgz -C oxford5k_images/
cd ../
echo data/oxford5k_images/hertford_000056.jpg >> list_images.txt
echo data/oxford5k_images/oxford_000317.jpg >> list_images.txt

这里我们抽取了 hertford_000056.jpg(Hertford 学院)与 oxford_000317.jpg(牛津某建筑)两张图片,构造出 list_images.txt 图像列表文件;oxford5k_features 目录将用于存放后续产出的 .delf 特征文件。

三、下载预训练 DELF 模型

接着下载在 Google Landmarks 数据集 v1(Google-Landmarks)上预训练的 DELF 模型,该模型出自 Detect-to-Retrieve 论文,相比 ICCV'17 原版模型带来了可观的检索精度提升:

# From tensorflow/models/research/delf/delf/python/examples/
mkdir parameters && cd parameters
wget http://storage.googleapis.com/delf/delf_gld_20190411.tar.gz
tar -xvzf delf_gld_20190411.tar.gz

解压后的目录应包含模型目录与 PCA 参数文件,它们与 delf_config_example.pbtxtmodel_pathmean_pathprojection_matrix_path 所指向的相对路径一一对应(见第四节)。

四、DELF 特征提取:extract_features.py

4.1 运行命令

安装、数据与模型就绪后,运行以下命令即可为 list_images.txt 中的两张图片提取 DELF 特征:

# From tensorflow/models/research/delf/delf/python/examples/
python3 extract_features.py \
  --config_path delf_config_example.pbtxt \
  --list_images_path list_images.txt \
  --output_dir data/oxford5k_features

从源码 extract_features.py 可以看到三个命令行参数的默认值与语义:

参数 默认值 说明
--config_path delf_config_example.pbtxt DelfConfig proto 文本配置文件路径,决定模型与提取策略
--list_images_path list_images.txt 待提取特征图片路径列表(每行一张,须为 JPG)
--output_dir test_features 特征输出目录,每张图输出同名、扩展名为 .delf 的文件

脚本的实际处理逻辑(extract_features.py)值得注意:它会用 text_format.Merge 解析 DelfConfig;若输出目录不存在则自动创建;若某张图对应的 .delf 文件已存在则直接跳过(方便断点续跑);每隔 100 张图打印一次处理耗时。每张图经 extractor.MakeExtractor(config) 构造的提取函数处理后,将关键点位置 locations、描述子 descriptors、尺度 scales、注意力分数 attention 四组数组通过 feature_io.WriteToFile 序列化写入文件。

4.2 .delf 特征文件格式

写入的特征文件对应 protobuf 定义的 DelfFeatures 消息。通过 feature_io.py 可以看出,每个特征点包含 y/x 坐标、scaleorientationstrength(即注意力分数)以及一个序列化的浮点描述子向量;读取时则调用 ReadFromFile 还原为 locations[N,2]scales[N]descriptors[N,depth]attention[N]orientations[N] 五组 NumPy 数组,若文件内无特征则返回五个空数组。

4.3 配置解析:DelfConfig 与多尺度金字塔

示例配置 delf_config_example.pbtxt 完整内容如下:

model_path: "parameters/delf_gld_20190411/model/"
image_scales: .25
image_scales: .3536
image_scales: .5
image_scales: .7071
image_scales: 1.0
image_scales: 1.4142
image_scales: 2.0
delf_local_config {
  use_pca: true
  # 注意:本示例导出的模型将 layer_name 与 iou_threshold 硬编码进了 checkpoint,
  # 因此此处这两个字段对提供的 extract_features.py 脚本不产生实际影响。
  layer_name: "resnet_v1_50/block3"
  iou_threshold: 1.0
  max_feature_num: 1000
  score_threshold: 100.0
  pca_parameters {
    mean_path: "parameters/delf_gld_20190411/pca/mean.datum"
    projection_matrix_path: "parameters/delf_gld_20190411/pca/pca_proj_mat.datum"
    pca_dim: 40
    use_whitening: false
  }
}

对照 delf_config.proto 的字段定义,可以深入理解每一项的底层影响:

  • model_path:指向导出的 TensorFlow SavedModel,MakeExtractor 内部通过 tf.saved_model.load 加载(extractor.py)。
  • image_scales:多尺度金字塔的缩放因子列表。DELF 会在每个尺度上分别提取特征后合并,示例中的 7 个尺度(0.25 → 2.0)用于提升尺度变化下的匹配鲁棒性。DELF 提取器会把全部尺度打包成 input_scales 张量一次性送入模型。
  • delf_local_config.use_pca:是否对描述子做 PCA 降维。开启后,extractor.py 会预先从 mean_path / projection_matrix_path 读取 PCA 均值与投影矩阵(必要时含方差文件),随后在 feature_extractor.py 的后处理中按“先 L2 归一化 → PCA 投影(可加白化)→ 再次 L2 归一化”的顺序压缩描述子,本示例将 1024 维原始描述子降至 40 维。
  • max_feature_num(默认 1000)与 score_threshold(默认 100.0):控制关键点筛选——超过阈值数量的特征按注意力分数从高到低截断,分数低于阈值的特征被丢弃。它们被构造为 input_max_feature_numinput_abs_thres 张量传入模型。
  • iou_threshold(默认 1.0,取值 0.0–1.0):NMS 的 IoU 阈值,两特征重叠度不超过该值则同时保留,否则仅保留注意力分数更高者。配置文件注释明确指出:该示例提供的导出模型把 layer_nameiou_threshold 固化在 checkpoint 内,因此改这两个字段不会生效。
  • layer_name:目标卷积层名(如 resnet_v1_50/block3),用于推算感受野参数,从而把特征反算回原图坐标。
  • use_resized_coordinates(proto 默认 false):为 false 时返回的关键点坐标会换算回原始输入图像坐标系;为 true 则直接使用缩放后图像的坐标。从 extractor.py 可见,当该字段为 false 时会对坐标除以缩放因子 scale_factors

此外 proto 还支持 use_local_features / use_global_features 开关(至少其一为 true)、max_image_size / min_image_size / use_square_images 图像尺寸约束,以及用于 DELG 全局特征的 DelfGlobalFeatureConfigimage_scales_ind 选择参与全局描述子聚合的尺度,并对各尺度描述子做求和池化与 L2 归一化)。这些字段主要服务于 DELG 指令文档 中的检索流程。

五、图像匹配:match_images.py

5.1 运行命令

特征提取完成后,执行以下命令对两张图做特征匹配:

python3 match_images.py \
  --image_1_path data/oxford5k_images/hertford_000056.jpg \
  --image_2_path data/oxford5k_images/oxford_000317.jpg \
  --features_1_path data/oxford5k_features/hertford_000056.delf \
  --features_2_path data/oxford5k_features/oxford_000317.delf \
  --output_image matched_images.png

match_images.py 共有 5 个参数(match_images.py):--image_1_path--image_2_path(用于可视化读取的原图路径)、--features_1_path--features_2_path(上一步产出的 .delf 特征文件),以及 --output_image(匹配结果图保存路径,默认 test_match.png)。

5.2 匹配原理:KD 树最近邻 + RANSAC 几何校验

脚本核心流程(match_images.py)包含三个阶段:

  1. 读取特征:调用 feature_io.ReadFromFile 分别载入两图的 locations 与 descriptors,并打印各自特征数量。
  2. 最近邻搜索:用 scipy.spatial.cKDTree 对图 1 的描述子建树,再对图 2 的每个描述子查询,搜索距离上界 _DISTANCE_THRESHOLD = 0.8;距离超过该阈值的点对视为无匹配,从而得到初筛(putative)匹配对集合。
  3. 几何校验(RANSAC):用 skimage.measure.ransac 以仿射变换 AffineTransform 为模型拟合内外点,参数为 min_samples=3residual_threshold=20max_trials=1000,最后打印内点数量 Found N inliers。这一步剔除了不符合整体几何约束的错误匹配。

最终脚本借助 matplotlib 将原图并排绘制,用 skimage.feature.plot_matches 标出内点对应连线,并调用 plt.savefig 输出到 --output_image 指定的图片。运行完成后生成的 matched_images.png 应与仓库内置的示例结果类似:

DELF 两两匹配可视化示例:蓝色连线表示经几何校验通过的局部特征对应点

(该图为仓库随附的 matched_images_example.jpg 参考结果,位于 examples 目录,也见于 DELF 总览 README。)

六、常见问题排查(Troubleshooting)

6.1 matplotlib 报 no display name and no $DISPLAY environment variable

在无图形界面的服务器/容器中运行时,matplotlib 可能因找不到显示环境而报错。解决办法之一是创建(或编辑)~/.config/matplotlib/matplotlibrc,加入一行:

backend : Agg

这样 matplotlib 会强制使用非交互的 Agg 后端,只负责把图保存到文件。实际上 match_images.py 自身已在代码头部执行了 matplotlib.use('Agg')match_images.py),可避免多数环境问题;若你的 Python 环境仍有拦截,通常与导入顺序或系统级配置有关,按上述方式显式配置 matplotlibrc 即可兜底。

6.2 scikit-image 相关报错

按安装文档默认装到的是 skimage 0.13.XX 或 0.14.1。若在使用 ransacplot_matchesfeature 等接口时遇到兼容性问题,升级到 0.14.1 以上版本即可:

pip3 install -U scikit-image

七、从快速入门到实际落地

跑通上面的流程后,你就掌握了 DELF 局部特征的完整链路:多尺度特征提取(extract_features.py)→ .delf 特征序列化(feature_io)→ KD 树匹配 + RANSAC 几何校验(match_images.py。在此基础上,可以进一步深入本仓库的相邻模块:

围绕本文,值得回到源码对照的关键文件有:extract_features.py(提取入口)、extractor.py(提取器构造、多尺度与 PCA 参数装配)、feature_extractor.py(PCA/白化与后处理)、match_images.py(匹配算法)、feature_io.py.delf 读写)、delf_config.proto(全部配置字段语义)以及 delf_config_example.pbtxt(可直接复用的示例配置)。迁移到自己的图片数据时,只需替换 list_images.txt 中的图像列表并保持配置与模型路径正确即可。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388