darktable AI 子系统开发指南:基于 ONNX Runtime 的推理后端架构与实战
【免费下载链接】darktabledarktable is an open source photography workflow application and raw developer项目地址: https://gitcode.com/GitHub_Trending/da/darktable
darktable 的 AI 子系统(AI Subsystem)是一套以 ONNX Runtime 为唯一推理后端的模块化框架,支撑交互式对象蒙版(SAM/SegNext)、神经降噪(RGB 域与 Raw 域)以及超分辨率放大等功能。本文以 dev-doc/AI.md 为核心,结合仓库源码深入剖析其三层架构、执行提供者(Execution Provider)解析、模型注册表与下载机制,并给出从零添加一个全新 AI 任务(Task)的完整步骤。读完本文,你将掌握 darktable AI 功能从模型加载、推理调度到接入 UI 的全链路开发方法。
一、架构总览:三层解耦的 AI 子系统
darktable 的 AI 子系统在逻辑上分为三层,职责清晰、依赖单向:
src/ai/ ONNX Runtime 后端(darktable_ai 静态库) backend.h 公共 API:类型定义、模型加载、推理 backend_common.c 环境、模型注册表、provider 解析 backend_onnx.c ONNX Runtime C API 封装 src/common/ai/ 高层 AI 模块(编译进 lib_darktable) segmentation.c/.h SAM/SegNext 交互式蒙版 restore.c/.h 通用 env/ctx 生命周期 + 模型加载器 restore_common.h restore_* 共享的私有结构体定义 restore_rgb.c/.h RGB 路径降噪 + 放大(分块推理、阴影提升、DWT 细节恢复) restore_raw_bayer.c/.h RawNIND Bayer 降噪(批处理 + 管道预览) restore_raw_linear.c/.h RawNIND linear/X-Trans 降噪 src/common/ai_models.c/.h 模型注册表、下载、偏好设置集成 src/gui/preferences_ai.c AI 偏好设置页签关键分离原则:src/ai/是一个完全自包含的静态库,不依赖任何 darktable 核心(只依赖 GLib 与 ONNX Runtime),这使得后端可以被独立测试和复用;而src/common/ai/负责把 AI 后端与 darktable 核心 API(DWT 小波、图像缓冲区、配置系统等)桥接起来,并仅在USE_AI=ON时编译。从 src/ai/backend.h 可以看到,后端头文件只包含<stdint.h>与<glib.h>,印证了这一自包含设计。
构建标志(Build Flags)
| Flag | 默认值 | 作用 |
|---|---|---|
USE_AI | OFF | 启用 AI 子系统 |
USE_AI_DOWNLOAD | ON(当USE_AI开启时) | 允许从仓库下载模型 |
当USE_AI=ON时,预处理器会定义HAVE_AI;启用下载时还会定义HAVE_AI_DOWNLOAD。在 src/common/ai_models.h 中,下载相关 API 全部包裹在#ifdef HAVE_AI_DOWNLOAD之内,说明下载能力是可选特性。
运行时开关:默认关闭,懒初始化
AI 功能在偏好设置中默认关闭。当关闭时:
- 不加载任何 ONNX Runtime;
- 不创建、不扫描任何模型目录;
- 所有
dt_ai_env_init()/dt_ai_load_model()调用直接返回 NULL; - 依赖 AI 的模块通过
reload_defaults()隐藏自身入口。
用户可在偏好设置 -> AI -> "enable AI features"中启用。启用后的初始化是延迟进行的:dt_ai_models_init_lazy()负责在运行时重新启用 AI 时执行延迟初始化(创建目录、读取 provider 配置、加载模型注册表、扫描本地模型),无需重启 darktable。对应实现见 src/common/ai_models.h 的注释与声明。
二、ONNX Runtime 集成:从加载到推理
2.1 初始化:进程级单例 + 懒加载
ONNX Runtime 通过 GLib 的g_once()单例机制懒初始化:
g_ort—OrtApi指针(每进程一份);g_env—OrtEnv实例(每进程一份)。
两者在首次模型加载或 provider 探测时创建,并在进程生命周期内常驻。
在 Linux 上,ONNX Runtime 始终通过g_module_open()懒加载,而非在进程启动时静态链接。这样做的目的是防止 GPU provider 库(如 MIGraphX/ROCm)在进程启动阶段就初始化——在不支持的 GPU 上,这些库可能在 darktable 有机会检查偏好设置之前就abort()崩溃。
2.2 模型加载调用链
dt_ai_load_model(env, model_id, model_file, provider) -> dt_ai_load_model_ext(env, model_id, model_file, provider, opt_level, dim_overrides, n_overrides) -> dt_ai_onnx_load_ext(model_dir, model_file, provider, opt_level, dim_overrides, n_overrides)加载一个模型的完整流程(对应 src/ai/backend_common.c 中dt_ai_load_model_ext的实现):
- 解析 provider:将
DT_AI_PROVIDER_CONFIGURED/DT_AI_PROVIDER_AUTO解析为具体 EP,并在此处统一应用模型声明的cpu_only安全约束; - 解析图优化级别:
DT_AI_OPT_DEFAULT时读取模型 manifest 中的ort_optimization,任何具体级别都是对 manifest 的显式覆盖; - 通过环境中的模型注册表把
model_id解析为目录路径; - 创建
OrtSessionOptions,开启全核 intra-op 并行; - 设置图优化级别(Graph Optimization Level);
- 应用符号维度覆盖(针对动态形状模型);
- 调用
_enable_acceleration()挂接选定的执行提供者; - 从
.onnx文件创建OrtSession; - 内省所有输入/输出的名称、类型与形状;
- 检测动态输出形状(任一维度 <= 0),以启用 ORT 内部分配输出模式。
注意dt_ai_load_model()只是dt_ai_load_model_ext()的便捷封装,默认参数为DT_AI_OPT_DEFAULT, NULL, 0(见 src/ai/backend_common.c)。
2.3 推理接口dt_ai_run与张量描述符
调用方通过dt_ai_tensor_t数组传入输入、接收输出:
typedef struct dt_ai_tensor_t { void *data; // 指向原始数据缓冲 dt_ai_dtype_t type; // 元素数据类型 int64_t *shape; // 维度数组 int ndim; // 维度数量 } dt_ai_tensor_t;该结构(定义于 src/ai/backend.h)不包含字节长度字段——缓冲长度由shape各维度乘积乘以sizeof(elem)隐式确定;data与shape指针均为借用,后端在dt_ai_run期间不会拷贝它们,调用方负责分配足够空间。辅助函数dt_ai_tensor_element_count()可计算形状对应的元素个数。
dt_ai_run()透明处理两个特殊场景:
- Float16 自动转换:若调用方提供 Float32 数据而模型期望 Float16,后端在推理前即时转换(输出方向同理);
- 动态输出形状:若任一输出带符号维度,ORT 在内部分配输出张量。推理完成后,后端把数据拷贝到调用方缓冲,并用实际维度回写调用方的 shape 数组。
2.4 图优化级别(Graph Optimization Levels)
| 级别 | 枚举值 | 适用场景 |
|---|---|---|
| All | DT_AI_OPT_ALL | 默认、最快,适用于大多数模型 |
| Basic | DT_AI_OPT_BASIC | 仅做常量折叠 + 冗余节点消除。SAM2 decoder必须使用(激进的优化会在动态维度上破坏形状推断) |
| Disabled | DT_AI_OPT_DISABLED | 预留,暂未使用 |
在 src/ai/backend.h 中还有一个额外的哨兵值DT_AI_OPT_DEFAULT = -1:由dt_ai_load_model传入时表示"读取 manifest 的ort_optimization字段(缺省回退 ALL)";而dt_ai_load_model_ext的调用方传具体级别即可覆盖 manifest。
2.5 符号维度覆盖(Symbolic Dimension Overrides)
带符号维度的模型(例如 SAM2 decoder 的num_labels)会让 ONNX Runtime 的形状推断失败。此时应使用dt_ai_load_model_ext()配合dt_ai_dim_override_t绑定具体值:
dt_ai_dim_override_t overrides[] = { { "num_labels", 1 } }; ctx = dt_ai_load_model_ext(env, id, file, provider, DT_AI_OPT_BASIC, overrides, 1);dt_ai_dim_override_t结构(src/ai/backend.h)只有name(符号维度名,如"num_labels")与value(具体值)两个字段。注意name指针只在加载调用期间被读取,后端会自行拷贝所需内容,调用方可在加载返回后立即释放字符串。
三、执行提供者(Execution Providers)
3.1 Provider 表
| Provider | 枚举 | 配置字符串 | 平台 |
|---|---|---|---|
| Auto | DT_AI_PROVIDER_AUTO | auto | 全部 |
| CPU | DT_AI_PROVIDER_CPU | CPU | 全部 |
| Apple CoreML | DT_AI_PROVIDER_COREML | CoreML | macOS |
| NVIDIA CUDA | DT_AI_PROVIDER_CUDA | CUDA | Linux, Windows |
| AMD MIGraphX | DT_AI_PROVIDER_MIGRAPHX | MIGraphX | Linux |
| Intel OpenVINO | DT_AI_PROVIDER_OPENVINO | OpenVINO | Linux, Windows, macOS (x86_64) |
| Windows DirectML | DT_AI_PROVIDER_DIRECTML | DirectML | Windows |
在 src/ai/backend_common.c 的dt_ai_providers[]表中可以直观看到每个 provider 的config_string、display_name与编译期平台守卫(#if defined(...)控制的available字段)。available决定哪些 provider 出现在 UI 中;运行时是否真的可用会另行探测(见 3.4 节)。
此外,DT_AI_PROVIDER_CONFIGURED(#define,值为 -1,见 src/ai/backend.h)是dt_ai_load_model()/dt_ai_load_model_ext()的哨兵值:它会在调用时从darktablerc读取用户的 provider 偏好。它不是真实 provider,绝不能存入配置或 provider 表。消费方遵循两条规则:需要尊重用户设置(如 restore、segmentation)就传CONFIGURED;需要强制特定 EP(如强制 decoder 走 CPU)就直传该 EP。
3.2 自动探测策略(AUTO)
当用户选择DT_AI_PROVIDER_AUTO(或从CONFIGURED解析得到 AUTO)时,后端优先尝试平台原生加速,失败则优雅回退:
- macOS:CoreML -> CPU
- Windows:DirectML -> CPU
- Linux:CUDA -> MIGraphX -> ROCm(legacy)-> CPU
3.3 运行时 Provider 加载
Provider 函数通过运行时动态符号查找加载(Unix 上用GModule/dlsym,Windows 上用GetProcAddress),从已链接的 ONNX Runtime 共享库中解析。这带来三个好处:
- 无编译期对 provider 专属头文件的依赖;
- provider 是可选的——缺失的符号被优雅处理;
- 同一份二进制同时兼容 CPU-only 与 GPU-enabled 的 ORT 构建。
3.4 Provider 探测:dt_ai_probe_provider()
dt_ai_probe_provider()在不加载模型的前提下测试某 provider 能否在运行时初始化。它创建临时的OrtSessionOptions,尝试挂接 provider,返回 1(可用)或 0(不可用)。偏好设置 UI 用它来在用户选中不可用的 provider 时给出警告。
3.5 多 GPU 设备选择(逃生通道)
对于同一厂商有多张 GPU 的系统(如笔记本的 iGPU+dGPU,或双 NVIDIA 卡工作站),默认device_id为0(平台枚举的第一块)。高级用户可通过配置键或环境变量覆盖(同时设置时环境变量优先):
| Provider | 配置键 | 环境变量 |
|---|---|---|
| CUDA | plugins/ai/cuda_device_id | DT_CUDA_DEVICE_ID |
| MIGraphX / ROCm | plugins/ai/migraphx_device_id | DT_MIGRAPHX_DEVICE_ID |
| DirectML | plugins/ai/dml_device_id | DT_DML_DEVICE_ID |
索引语义遵循各 provider 自身的枚举方式:
- CUDA索引与
nvidia-smi一致(并尊重CUDA_VISIBLE_DEVICES); - MIGraphX / ROCm索引对应
rocminfo中的 GPU agent 顺序; - DirectML索引对应
IDXGIFactory1::EnumAdapters1顺序。
OpenVINO 与 CoreML 是单设备或自管理,不读取 device_id 键。修改后需重启 darktable 生效。后端提供了dt_ai_device_id_changed_since_load()等辅助函数来检测"配置已变但进程内 ORT 仍是旧状态"的情形(见 src/ai/backend.h)。
3.6 ONNX Runtime 发行包来源
| 平台 | 包来源 | 包含的 Providers |
|---|---|---|
| macOS | GitHub releases(CPU) | CPU、CoreML(经 Apple frameworks) |
| Linux (x86_64) | GitHub releases(GPU) | CPU、CUDA、TensorRT |
| Linux (aarch64) | GitHub releases(CPU) | 仅 CPU |
| Linux | 系统包(发行版) | 仅 CPU(Debian/Ubuntu/Fedora 的包不含 GPU provider) |
| Windows | NuGet(DirectML 变体) | CPU、DirectML |
构建系统 cmake/modules/FindONNXRuntime.cmake 在系统找不到 ONNX Runtime 时会自动下载合适的包:Linux x86_64 默认下载 GPU 变体以启用 CUDA 加速;而系统包(如 Debian/Ubuntu 的libonnxruntime-dev)仅含 CPU,不含 GPU provider。
四、模型发现与注册表(Model Registry)
4.1 目录布局
模型通过扫描子目录中的config.json被发现,扫描路径为:
- 传入
dt_ai_env_init()的自定义路径(分号分隔); <user_data_dir>/darktable/models/- Linux:
~/.local/share/darktable/models/ - Windows:
%APPDATA%\darktable\models\ - macOS:
~/.local/share/darktable/models/
- Linux:
重复 ID 以先发现者为准(重复项被跳过)。模型下载(ai_models.c)也解压到同一路径,因此下载的模型立即可被发现。扫描实现见 src/ai/backend_common.c 的_scan_directory/_scan_all_paths:逐个读取config.json解析字段,并用哈希表model_paths记录id -> 路径映射以去重。
用户还可以通过配置键plugins/ai/models_path覆盖模型目录(dt_ai_resolve_models_path_override()支持~展开,见 src/ai/backend_common.c)。
4.2 config.json 格式
每个模型目录必须包含config.json:
{ "id": "mask-object-segnext-b2hq", "name": "mask segnext vitb-sax2 hq", "description": "SegNext ViT-B SAx2 HQ fine-tuned for interactive masking", "task": "mask", "arch": "segnext", "backend": "onnx" }| 字段 | 必填 | 默认值 | 说明 |
|---|---|---|---|
id | 是 | -- | 唯一标识符 |
name | 是 | -- | UI 中显示的展示名 |
description | 否 | "" | 简短描述 |
task | 否 | "general" | 任务类型:"denoise"、"upscale"、"mask"、"depth" |
backend | 否 | "onnx" | 后端类型(目前仅支持"onnx") |
arch | 否 | "" | 模型架构(如"sam2"、"segnext") |
num_inputs | 否 | 1 | 模型输入数量 |
除了这些基础字段,后端还支持一组可选行为提示,存放在attributes对象中,例如:
"attributes": { "shadow_boost": true, "tile_factor": 1.5, "color_space": "sRGB" }dt_ai_model_attribute_*系列访问器(src/ai/backend.h)会按需解析 JSON:缺失的键或类型不符的键返回传入的默认值(bool/string 变体返回 FALSE/NULL)。dt_ai_model_attribute_string()支持点分路径(如"variants.bayer.onnx"),中间段必须是 JSON 对象,实现见 src/ai/backend_common.c。
类似地,manifest 还可以声明cpu_only(数组或按 onnx 文件名 stem 分组的对象,声明哪些 EP 对模型不安全)、coreml_format("neuralnetwork"或"mlprogram")、ort_optimization与ort_optimization_provider(按 provider 覆盖图优化级别)。这些字段会被后端序列化为 JSON 字符串存入dt_ai_model_info_t(src/ai/backend.h)。
4.3 模型 ID 命名约定
模式:<task>-<model>[-<size>]
- 全部小写、连字符分隔;
- 第一个组件是任务类型(
denoise、mask、upscale、depth); - 蒙版任务的第二个组件是子任务(
object); - 存在多种尺寸时追加尺寸后缀(
small、base、large)。
示例:denoise-nind、mask-object-sam21-small、upscale-bsrgan、mask-depth-da2-small。
当前仓库内置的模型目录 data/ai_models.json 包含:mask-object-sam21-small、mask-object-segnext-b2hq、denoise-nind、rawdenoise-nind、upscale-realplksr五个条目,每个都带min_version与default标记。
五、模型仓库(darktable-ai)与下载机制
darktable 中可下载的模型作为 release 资产托管在darktable-ai 仓库中。该仓库还包含:
- 转换脚本——将 PyTorch 模型导出为 darktable 期望格式的 ONNX(正确的 I/O 名称、动态轴、把插值烘焙进计算图等);
- 打包脚本——把
config.json+ ONNX 文件打包为.dtmodel归档(zip)用于分发; - 模型元数据——
ai_models.json源文件,列出所有可用模型及其任务、描述、资产文件名。
下载流程:
- darktable 读取随构建分发的 data/ai_models.json,得知存在哪些模型;
- 用户在 AI 偏好设置中点击"下载";
ai_models.c通过 GitHub API 从 darktable-ai 最新 release 拉取.dtmodel资产;- 归档解压到
~/.local/share/darktable/models/; - 模型立即被
dt_ai_env_init()发现。
仓库在darktablerc中配置:
plugins/ai/repository=darktable-org/darktable-ai从 src/common/ai_models.h 可以看到,仓库可以额外发布未包含在捆绑目录中的模型(versions.json是 release 内容的超集),支持第三方仓库(plugins/ai/third_party_repositories)与 sha256 校验和验证;模型还有DT_AI_MODEL_UPDATE_AVAILABLE/DT_AI_MODEL_UPDATE_REQUIRED的版本状态机——UPDATE_REQUIRED表示当前代码无法使用已安装模型,UPDATE_AVAILABLE只是软提示。
向仓库添加新模型
- 用转换脚本把模型导出为 ONNX(或参照现有示例编写新脚本);
- 创建带正确
id、task、arch字段的config.json; - 打包为
.dtmodel归档; - 在 darktable-ai 的
ai_models.json中新增模型条目; - 发布新 release,并把
.dtmodel作为资产附上; - 更新 darktable 源码中的 data/ai_models.json,加入新模型条目。
用户也可以从本地.dtmodel文件安装模型:dt_ai_models_install_local()(src/common/ai_models.h)接受 zip 归档路径。
六、如何添加一个全新的 AI 功能
这是 dev-doc/AI.md 的核心实战章节,完整步骤如下。
Step 1:创建 AI 模块
在src/common/ai/下创建你的处理模块。使用不透明类型(opaque types)封装,模块内部包装ai/backend.h的dt_ai_*调用,对外暴露干净的公共 API:
// src/common/ai/your_task.h #pragma once #include <glib.h> typedef struct dt_your_task_env_t dt_your_task_env_t; typedef struct dt_your_task_ctx_t dt_your_task_ctx_t; dt_your_task_env_t *dt_your_task_env_init(void); void dt_your_task_env_destroy(dt_your_task_env_t *env); dt_your_task_ctx_t *dt_your_task_load( dt_your_task_env_t *env); void dt_your_task_free(dt_your_task_ctx_t *ctx); gboolean dt_your_task_available( dt_your_task_env_t *env); int dt_your_task_process( dt_your_task_ctx_t *ctx, const float *in, float *out, int width, int height);// src/common/ai/your_task.c #include "common/ai/your_task.h" #include "ai/backend.h" #include "common/ai_models.h" #define TASK_KEY "your_task" struct dt_your_task_env_t { dt_ai_environment_t *ai_env; }; struct dt_your_task_ctx_t { dt_ai_context_t *ai_ctx; dt_your_task_env_t *env; }; dt_your_task_ctx_t *dt_your_task_load( dt_your_task_env_t *env) { if(!env) return NULL; char *model_id = dt_ai_models_get_active_for_task(TASK_KEY); if(!model_id || !model_id[0]) { g_free(model_id); return NULL; } dt_ai_context_t *ai_ctx = dt_ai_load_model( env->ai_env, model_id, NULL, DT_AI_PROVIDER_CONFIGURED); g_free(model_id); if(!ai_ctx) return NULL; dt_your_task_ctx_t *ctx = g_new0(dt_your_task_ctx_t, 1); ctx->ai_ctx = ai_ctx; ctx->env = env; return ctx; } int dt_your_task_process( dt_your_task_ctx_t *ctx, const float *in, float *out, int width, int height) { // prepare input tensor (convert colorspace, layout) // call dt_ai_run(ctx->ai_ctx, ...) // post-process output return 0; }这段示例揭示了一条关键约定:dt_ai_models_get_active_for_task(TASK_KEY)(定义于 src/common/ai_models.h)按任务从集中式配置键plugins/ai/models/active/{task}解析当前激活的模型;若未设置则回退到该任务的默认下载模型,并写回配置键。加载时传入DT_AI_PROVIDER_CONFIGURED,让 provider 决策尊重用户偏好。
Step 2:注册进构建系统
在 src/CMakeLists.txt 的USE_AI分支中添加源文件:
FILE(GLOB SOURCE_FILES_AI "common/ai_models.c" "common/ai/segmentation.c" "common/ai/restore.c" "common/ai/restore_rgb.c" "common/ai/restore_raw_bayer.c" "common/ai/restore_raw_linear.c" "common/ai/your_task.c" # add here ... )Step 3:添加模型条目
在 data/ai_models.json 中添加模型:
{ "id": "your-task-model-name", "name": "your task model name", "description": "description of the model", "task": "your_task", "github_asset": "your-task-model-name.dtmodel", "default": true }.dtmodel文件是一个 zip/tar 归档,内含config.json和 ONNX 模型文件(一个包可含多个 ONNX,如 rawdenoise 的model_bayer.onnx+model_linear.onnx)。
Step 4:创建 UI 消费方
- lighttable 模块:创建
src/libs/your_module.c; - darkroom IOP:创建
src/iop/your_module.c。
UI 模块只能包含你的src/common/ai/头文件——绝不直接包含ai/backend.h或common/ai_models.h,以维持分层边界:
#include "common/ai/your_task.h" // in gui_init or job startup: dt_your_task_env_t *env = dt_your_task_env_init(); // check availability: gboolean avail = dt_your_task_available(env); // process: dt_your_task_ctx_t *ctx = dt_your_task_load(env); dt_your_task_process(ctx, input, output, w, h); dt_your_task_free(ctx);七、可用任务一览与消费方
| 任务 | 任务键 | API | 消费方 |
|---|---|---|---|
| 对象蒙版 | "mask" | src/common/ai/segmentation.h | src/develop/masks/object.c |
| Raw 降噪(Bayer) | "rawdenoise" | src/common/ai/restore_raw_bayer.h | src/libs/neural_restore.c |
| Raw 降噪(Linear) | "rawdenoise" | src/common/ai/restore_raw_linear.h | src/libs/neural_restore.c |
| 降噪 | "denoise" | src/common/ai/restore_rgb.h | src/libs/neural_restore.c |
| 放大 | "upscale" | src/common/ai/restore_rgb.h | src/libs/neural_restore.c |
各任务的具体模型要求、I/O 规格、分块(tiling)策略、色彩空间约定、ONNX 导出说明与 config.json 示例,详见配套参考文档AI_Tasks.md。摘要如下:
- 对象蒙版(mask):SAM 2.1 与 SegNext 两种架构。图片先被导出为 sRGB uint8,经 SAM encoder 编码为图像嵌入(每图一次、带缓存与磁盘缓存),用户点击放置前景/背景点后,轻量 decoder 产出蒙版;前一低分辨率蒙版会反馈回 decoder 做迭代精化(
has_mask_input区分首击 0.0 与精化 1.0)。dt_seg_reset_prev_mask()只清蒙版缓存,dt_seg_reset_encoding()清全部(换图时调用)。SAM2 decoder 输出带num_labels符号维度,因此需要用DT_AI_OPT_BASIC+ 维度覆盖加载; - Raw 降噪(rawdenoise):在 darktable 管线之前对 raw CFA 马赛克做传感器级降噪,输出 DNG 再导入,可被完整管线正常调色。Bayer 变体把 2T×2T CFA 块打包为 4 通道 T×T 张量(RGGB 顺序,非 RGGB 传感器强制裁剪到 RGGB 原点),模型内部经 PixelShuffle 去马赛克后输出 3 通道 camRGB;Linear 变体(X-Trans、Foveon 等)先跑最小 darktable 管线(rawprepare→highlights→demosaic)得到 3 通道浮点,再经
lin_rec2020矩阵与曝光提升后推理; - 降噪(denoise):对完整管线导出的线性 Rec.709 图像做 sRGB 域推理,可选 DWT 小波细节恢复把原始细纹理混合回结果,输出 TIFF(内嵌 ICC 与 EXIF)后自动导入;
- 放大(upscale):2x/4x 超分辨率,同一模型可经
model_x2.onnx/model_x4.onnx提供两种倍率,TIFF 输出采用逐扫描线流式写入以应对超大输出(4x 放大 6000 万像素原图约需 3.6GB 内存)。
neural-restore 消费方(denoise / upscale / rawdenoise)会把输出写到源文件的同级文件(TIFF 或 DNG),再经_import_image自动导入库中,与源图像分组,并继承源图像的用户标签、星级、颜色标签等元数据,因此输出会出现在源图像所在的任何筛选视图或收藏集中。注意:darktable|*内部自动标签会被跳过。
八、添加新的执行提供者(EP)
如果需要接入一个新的 ONNX Runtime 执行提供者,按以下 5 步操作:
- 在 src/ai/backend.h 的
dt_ai_provider_t枚举中添加枚举值(必须放在DT_AI_PROVIDER_COUNT之前); - 在
dt_ai_providers[]表中添加条目,包含配置字符串、显示名与平台守卫; - 在 src/ai/backend_onnx.c 的
_enable_acceleration()中添加case; - 在 src/ai/backend_onnx.c 的
dt_ai_probe_provider()中添加case; - 文件中的
_Static_assert会确保表与枚举保持同步(漏改即编译失败)。
九、小结
darktable 的 AI 子系统通过"自包含后端(src/ai)+ 高层任务模块(src/common/ai)+ 注册表/偏好集成(src/common/ai_models.c、src/gui/preferences_ai.c)"三层结构,把 ONNX Runtime 的能力以可扩展、可配置、可下载模型的方式接入摄影工作流。理解本文的 provider 解析、模型 manifest 契约与"UI 只依赖src/common/ai/头文件"的分层纪律,是扩展新任务与新执行提供者的关键。深入各任务细节请继续阅读 AI_Tasks.md,源码级参考可查阅 backend.h、backend_common.c 与 ai_models.h。
【免费下载链接】darktabledarktable is an open source photography workflow application and raw developer项目地址: https://gitcode.com/GitHub_Trending/da/darktable
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考