- 计算机视觉
- 深度学习
- 图像处理
【免费下载链接】kornia
🐍 Geometric Computer Vision Library for Spatial AI
导读
本文围绕 Kornia 仓库中 changelog 条目(+migration-023.added.md,对应 PR #4178)所记录的一次文档结构改革展开:Models 文档章节的每个页面现在都以"运行该模型的最短脚本 + 模型在真实输入上的输出图"开头,而论文卡片被移到了页面底部。通过深入阅读渲染脚本 docs/generate_model_examples.py、各模型页面 RST 源文件与构建配置 docs/source/conf.py,本文将完整还原这套"示例图预先渲染并提交、文档构建零权重零样例图依赖"的机制,并给出如何为一个新模型页面接入这套流程的实操方案。
changelog 条目解读:一次面向读者的文档结构改革
changelog.d/+migration-023.added.md原文如下:
Every page in theModelssection of the docs now opens with the shortest script that runs the model and a figure of its output on a real input, with the paper card moved to the bottom. The figures are rendered by
docs/generate_model_examples.pyand committed underdocs/source/_static/img/models/, so the docs build needs neither the weights nor the sample images. (#4178)
这条变更记录包含三个层面的设计决策,缺一不可:
- 信息架构重排(面向读者):每个模型页面从"论文卡片开路"改为"可运行代码开路"。读者打开页面的第一眼看到的是"最短脚本 + 真实输出图",先建立"这个模型怎么用、输出长什么样"的直觉,论文信息下沉到页面底部作为延伸阅读;
- 图例生成自动化(面向作者):页面中的输出图统一由
docs/generate_model_examples.py渲染,而不是手工 PS 或截图; - 构建解耦(面向 CI/基础设施):渲染好的图片以静态资源形式提交进仓库(
docs/source/_static/img/models/),因此文档构建过程既不需要下载模型权重,也不需要下载样例图片,构建时间和网络依赖被严格控制。
这套模式在当前仓库中已经完整落地:docs/source/_static/img/models/下共提交了 14 张示例图(rt_detr.jpg、yunet.jpg、segment_anything.jpg、mobile_sam.jpg、efficient_vit.jpg、tiny_vit.jpg、vit.jpg、vit_mobile.jpg、loftr.jpg、sold2.jpg、hardnet.jpg、affnet.jpg、dexined.jpg、defmo.jpg),与 14 个模型页面一一对应。
上图即由脚本渲染并提交的 LoFTR 页面示例图:左右两张真实视角照片并排,绿色连线连接keypoints0[i]与keypoints1[i]的匹配点对。
Models 章节现状:统一骨架下的 14 个模型页面
Models 章节的入口是 docs/source/models/index.rst,它以一张清单表列出全部模型,每行给出Model / Task / Venue / Licence四列信息,并按任务分组(Object detection、Segmentation、Image classification、Local features and matching、Edge detection、Enhance):
| 分组 | 模型 |
|---|---|
| 目标检测 | RT-DETR、YuNet |
| 分割 | Segment Anything (SAM)、MobileSAM、EfficientViT |
| 图像分类 | ViT、MobileViT、TinyViT |
| 局部特征与匹配 | LoFTR、HardNet、AffNet、SOLD2 |
| 边缘检测 | DexiNed |
| 增强 | DeFMO |
在 docs/source/conf.py 的_landing_page_counts()中可以看到,models计数正是通过扫描models/目录下除index.rst外的 RST 文件数得到的(model_pages = [entry for entry in os.listdir("models") if entry.endswith(".rst") and entry != "index.rst"]),目前为 14,与示例图数量一致。
每个模型页面的骨架完全一致,以 docs/source/models/loftr.rst 为例,顺序为:
- 页头:
.. meta::描述(供搜索引擎与社交分享抓取)+ 类型徽章(如Image matching、Apache-2.0); - 简介段落:一两句话说明模型能力与输入输出约定;
Run it章节:可复制的最小运行脚本;.. figure::指令:引用docs/source/_static/img/models/下的真实输出图,并附 alt 文本与图注;Paper章节:论文卡片(摘要、任务、数据集、会议、许可证、作者),位于页面最底部。
"Run it":页面顶部的可运行最短脚本
"最短脚本"(shortest script)是这次改革的核心交付物——每个页面必须给出一个能跑通该模型的代码块。综合各页面源码,这套脚本有几个共同约定:
- 输入统一为
(1, 3, H, W)、取值范围[0, 1]的 float 张量; - 通过
kornia.io.load_image加载本地图片,通过 Builder 类(如RTDETRDetectorBuilder、EdgeDetectorBuilder)或from_config/pretrained=...一键加载预训练权重; - 推理放在
torch.no_grad()中。
以 docs/source/models/rt_detr.rst 的目标检测为例,这是目前最短的完整流程:
from kornia.io import load_image from kornia.contrib.object_detection import RTDETRDetectorBuilder image = load_image("delorean.png")[None] # (1, 3, H, W) float in [0, 1] detector = RTDETRDetectorBuilder.build("rtdetr_r18vd") # downloads the COCO weights; runs at 640 px detections = detector(image) # list with one (D, 6) tensor per image: class id, score, x, y, w, h for class_id, score, x, y, w, h in detections[0].tolist(): print(f"class {int(class_id)}: {score:.2f} at ({x:.0f}, {y:.0f}) size {w:.0f}x{h:.0f}")关键点:Builder 把 resize/normalise 预处理与 box 后处理全部打包,用户拿到的是"原图像素坐标系下的class_id, score, x, y, w, h",并可通过confidence_threshold、detector.visualize(...)、detector.to_onnx(...)进一步控制;可用变体按速度从快到慢为rtdetr_r18vd、rtdetr_r34vd、rtdetr_r50vd_m、rtdetr_r50vd、rtdetr_r101vd。
上图为 RT-DETR 页面示例图:输入图片与rtdetr_r18vd返回的检测框(COCO 类别 id 2 即 car),展示了"真实输入 → 真实输出"的文档目标。
LoFTR 页面(docs/source/models/loftr.rst)则展示了另一种形态——直接返回匹配点对而非绘制结果:
import torch from kornia.color import rgb_to_grayscale from kornia.feature import LoFTR from kornia.io import load_image img1 = load_image("church_1.png")[None] # (1, 3, H, W) float in [0, 1] img2 = load_image("church_2.png")[None] matcher = LoFTR(pretrained="outdoor").eval() # 'outdoor' (MegaDepth) or 'indoor' (ScanNet) with torch.no_grad(): out = matcher({"image0": rgb_to_grayscale(img1), "image1": rgb_to_grayscale(img2)}) pts1, pts2, conf = out["keypoints0"], out["keypoints1"], out["confidence"] # (N, 2) (x, y) pixels, (N, 2), (N,)页面还特别注明:两张图允许不同尺寸,out["batch_indexes"]用于区分批量中每个匹配属于哪对图像;得到的匹配对可直接喂给kornia.geometry.ransac.RANSAC或find_homography_dlt估计视图间几何关系。
输出图如何生成:generate_model_examples.py 工作机制
示例图并非手绘或截图,而是由 docs/generate_model_examples.py 程序化渲染。该脚本的设计有几个值得学习的点。
装饰器注册机制
脚本通过一个@figure装饰器把所有渲染函数收集进FIGURES字典,函数名去掉figure_前缀即图名:
FIGURES: dict = {} def figure(fn): FIGURES[fn.__name__.removeprefix("figure_")] = fn return fn这样__main__入口只需遍历命令行参数即可按名执行:
if __name__ == "__main__": wanted = sys.argv[1:] or list(FIGURES) unknown = [n for n in wanted if n not in FIGURES] if unknown: raise SystemExit(f"unknown figure(s) {unknown}; choose from {sorted(FIGURES)}") for n in wanted: print(f"== {n}") FIGURES[n]()因此有两种运行方式:
python docs/generate_model_examples.py # 渲染全部 14 个模型的示例图 python docs/generate_model_examples.py loftr sold2 # 只渲染指定子集未知名称会被显式拒绝并列出可选集合,避免打错名字。
关键辅助函数与全局约定
mpl.use("Agg"):在导入 pyplot 之前切换到无头后端,保证脚本可在无显示环境的 CI 上运行;torch.manual_seed(0):固定随机种子,使多次渲染输出可复现;sample(name, size=None):从 kornia data 仓库下载单张(1, 3, H, W)float 图(get_sample_images(..., resize=size, as_list=True)),供各模型共用;knchurch():通过torch.hub.load_state_dict_from_url下载双视图匹配数据(img1/img2);imagenet_classes():拉取 ImageNet-1k 类别名用于 top-k 可视化;show(ax, img, title):把张量转为图像绘制到子图,灰度图自动使用 gray colormap;save(fig, name):以 JPEG(dpi=110、quality=88)写入docs/source/_static/img/models/,目录不存在时自动创建;topk_bars(ax, logits, names, title):绘制 softmax 后 top-5 类别的横向条形图。
每个 figure 函数都"与页面脚本保持同步"
脚本文件头的 docstring 明确写了一条维护约定:
Each
figure_<name>function runs the model the same way the corresponding page's "Run it" snippet does (same builder, weights, inputs and prompts) and then draws the result; keep the two in sync when either changes.
也就是说,页面 RST 里的 "Run it" 代码与脚本里的 figure 函数必须使用同一套 builder、权重、输入和提示词,以保证文档正文的代码示例与页面图片展示的是完全一致的行为。例如figure_rt_detr与rt_detr.rst的代码块都用RTDETRDetectorBuilder.build("rtdetr_r18vd")处理同一张delorean.png;figure_loftr与loftr.rst都用LoFTR(pretrained="outdoor")匹配knchurch双视图。
面向不同模型的渲染形态
脚本按任务类型提供了多种可视化范本:
- 检测类(
figure_rt_detr、figure_yunet):原图 + 画框结果并排,框上标注类别 id 与分数;YuNet 还会叠加 5 个关键点; - 分割类(
_sam_figure供figure_segment_anything/figure_mobile_sam复用):用VisualPrompter先set_image编码一次,再分别用点提示(K 个 N 点,label 1=前景 0=背景)与框提示(Boxes.from_tensor(..., mode="xyxy"))查询,把预测 mask 以绿色叠加渲染并展示预测 IoU;其中"encode once, query many times"正是 docs/source/models/segment_anything.rst 中 prompter API 的核心用法; - 匹配类(
figure_loftr、figure_sold2、figure_hardnet):双图拼接后画连线,LoFTR 还会在标题中标出匹配数与平均置信度; - 特征类(
figure_affnet、figure_vit、figure_efficient_vit、figure_tiny_vit、figure_vit_mobile):展示 LAF 边界、patch token 范数网格、各 stage 平均激活图或 top-5 类别条形图; - 边缘/增强类(
figure_dexined、figure_defmo):边缘概率图以"深色=边缘"呈现;DeFMO 用 24 帧球体飞行的合成均值构造运动模糊输入,再展示去模糊后的子帧(RGBA alpha 混合到背景)。
图片提交 vs 构建时生成:为什么 docs build 不依赖权重与样例图
这是本次文档改革最关键的工程收益,其实现机制在于区分了两个示例图生成脚本:
| 脚本 | 何时运行 | 产物 | 是否下载权重 |
|---|---|---|---|
| docs/generate_model_examples.py | 手动运行一次,产物提交进仓库 | docs/source/_static/img/models/*.jpg(14 张) | 是(RT-DETR、SAM、SOLD2、DeFMO 等预训练权重) |
| docs/generate_examples.py | 每次 Sphinx 构建时自动运行 | docs/source/_static/img/*.png(增强、颜色、滤波等示例图) | 是(KeyNet、DISK、ALIKED、XFeat 四个模型) |
后者由 docs/source/conf.py 在构建期通过importlib.util.spec_from_file_location("generate_examples", "../generate_examples.py")加载并直接调用generate_examples.main()(第 88-93 行);前者则刻意不接入构建流程。generate_model_examples.py的 docstring 解释了原因:
Unlike
generate_examples.pythis script isnotrun by the Sphinx build: it downloads several pretrained checkpoints (RT-DETR, SAM ViT-B, SOLD2, DeFMO, ...) and runs them on the CPU, which is too slow and too download-heavy for a docs build. Run it once when a model or its API changes and commit the resulting figures underdocs/source/_static/img/models/.
即:模型推理 + 权重下载对每次文档构建来说"太慢、太重",因此改为变更驱动的离线渲染 + git 提交静态图。save()内部用OUT.mkdir(parents=True, exist_ok=True)保证提交目录存在,图片以确定性路径落盘,RST 页面用.. figure:: /_static/img/models/<name>.jpg直接引用。由此,任何环境下跑sphinx-build(或docs/Makefile中的make html)都无需联网下载模型权重与样例图,构建结果始终可用。
此外,docs/source/conf.py 还通过_landing_page_counts()把模型页面数、各模块算子数等动态数值注入rst_epilog替换符(|count-models|等),并统一为每个页面注入 Open Graph/Twitter 社交标签,说明"示例图 + 最短脚本"只是这套文档工程化的一部分。
从源码结构看:如何为新增模型页面接入这套流程
综合脚本与页面的约定,为一个新模型添加"最短脚本 + 真实输出图"页面的流程可以概括为:
- 写页面骨架:在 docs/source/models/ 下新建
<name>.rst,按"meta 描述 → 徽章 → 简介 → Run it 代码块 → figure 引用 → Paper 卡片"的顺序组织,并在 index.rst 的清单表与对应分组的 toctree 中登记; - 写 figure 函数:在 docs/generate_model_examples.py 中新增
figure_<name>(),用@figure装饰;函数内使用与页面 "Run it" 片段完全一致的 builder、权重、输入与提示词,通过sample()/knchurch()获取真实输入,最后save(fig, "<name>"); - 离线渲染并提交:运行
python docs/generate_model_examples.py <name>,确认docs/source/_static/img/models/<name>.jpg生成(若函数名拼写有误,脚本会直接报unknown figure(s)并列出可用名称);将该 jpg 提交进仓库; - 保持同步:后续若模型 API 或默认权重变更,需同时更新页面代码块与 figure 函数,否则文档代码示例与示例图会不一致——这是脚本 docstring 明确要求的维护纪律。
总结
+migration-023.added.md记录的并非一次简单的排版调整,而是一套可复用的"模型文档工程化"模式:以最短可运行脚本满足"拿来即用",以程序化渲染的真实输出图建立"所见即所得"的信任,以"离线渲染 + 静态图提交"将权重下载与推理成本挡在文档构建之外。对于想要为 Kornia 增加新模型页面、或在自己的项目里复刻类似文档体系的开发者,docs/generate_model_examples.py 与 docs/source/models/ 的组合是一个完整的参考实现。
- 计算机视觉
- 深度学习
- 图像处理
【免费下载链接】kornia
🐍 Geometric Computer Vision Library for Spatial AI
相关推荐
Kornia 文档 Models 章节重构:以「最短可运行脚本 + 真实输出图」开篇的模型文档实践
Kornia 文档 Models 章节重构:以「最短可运行脚本 + 真实输出图」开篇的模型文档实践 导读 本文基于 Kornia 仓库的迁移记录 changel
人工智能计算机视觉深度学习图像处理Yaegi文档示例:可运行代码片段最佳实践
Yaegi文档示例:可运行代码片段最佳实践 你是否在开发Go项目时遇到过这些痛点?需要动态执行代码却不想重新编译整个项目?希望在应用中嵌入脚本功能但找不到轻量级
编程语言解释器语言运行时Shieldstral-1.0-3B模型架构解密:Pixtral视觉编码器与Ministral底座的完美结合
Shieldstral 1.0 3B模型架构解密:Pixtral视觉编码器与Ministral底座的完美结合 Shieldstral 1.0 3B是一款革命性的
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考