请输入
菜单

fixSharedMemoryDll — filter.* 命令族接口手册

作者: JT下载

fixSharedMemoryDll — filter.* 命令族接口手册

本文档专门讲 filter.* 命令家族(像素级 2D 图像处理)。

协议总览、命令家族分布、错误码表、共享内存配置等通用内容请看 fixSharedMemory_dll_README.md

适用版本:fixSharedMemoryDll v2.0.0+,FIX 主程序 build ≥ 3685。


1. 命令一览

命令 用途 输出尺寸
filter.sr FIX 超分辨率(×1 增强 / ×2 / ×3 / ×4 上采样;psnrMode=true 走自然模式,不出现锐化伪影) scale1 同尺寸;scale2 ×2(快速档);scale3 ×3;scale4 ×4
filter.sm Smart Denoising(非局部均值降噪) 同输入
filter.um Unsharp Mask 锐化 同输入
filter.clahe 限制对比度自适应直方图均衡(与 W/L 同语义,RGB 走 Lab L 通道) 同输入
filter.hef High-Emphasis Filter(频域高通强调) 同输入(输出 8U 单通道,彩色经 Lab L 处理后回 BGR)
filter.edgeEnhance 边缘增强(5×5 拉普拉斯类核) 同输入
filter.anisoDiffusion 各向异性扩散(Perona-Malik 保边降噪) 同输入
filter.gamma Gamma 校正(亮度非线性映射) 同输入
filter.exposure 曝光补偿(线性 EV stops) 同输入
filter.bc 亮度 + 对比度(Photoshop 经典) 同输入
filter.shadowHighlight 暗部提升 + 亮部压缩(参数化 tone curve) 同输入
filter.gauss OpenCV 高斯模糊(基础工具,与 W/L 无关) 同输入
filter.applyEffect 复现 FIX W/L 控件保存的 .json 效果(curve + 多 filter 一次性应用) 取决于栈中是否含 SR(同输入 / ×N)

所有 filter.* 命令的输入图像通过共享内存传给服务端,输出图像通过共享内存返回客户端。
并发模型:服务端 FIFO 串行处理所有图像处理请求,无背压。

RGB 支持:除 filter.sr 外的所有 W/L 滤镜都通过 applyOnLuminance 走 Lab L 通道处理彩色图(不偏色)。filter.edgeEnhance 通过 cv::filter2D 直接 per-channel 处理。

与 W/L 控件等价filter.{sm,um,clahe,hef,edgeEnhance,anisoDiffusion,gamma,exposure,bc,shadowHighlight} 的算法与参数语义与 W/L 控件的"已应用滤镜栈"完全一致,可直接用同一份 JSON 在 SHM 通道复现 UI 看到的效果。


2. 通用调用结构

2.1 数据结构

c 复制代码
typedef struct FSImageProcParamsC {
    const char* command;          // 必填:"filter.sr"
    const char* paramsJson;       // 可空:命令参数 JSON(UTF-8)
    const char* teachingFile;     // 可空:teach.* 用
    const char* resultPath;       // 可空:服务端落盘路径(filter.* 也支持,命中后跳过 SHM 回传)
                                  //       paramsJson["option.resultPath"] 优先级更高
    int         timeoutMs;        // 0=默认 300000ms
} FSImageProcParamsC;

typedef struct FSImageProcResultC {
    int32_t  procStatus;          // 0=OK;详见错误码表
    int32_t  taskStatus;
    uint32_t outRows, outCols, outChannels;  // 服务端落盘模式下全为 0(SHM 跳过)
    int      outImageType;        // FS_IMAGE_C_RGB24 / FS_IMAGE_C_GRAY8 ...
    uint64_t outStride;
    void*    outImage;            // DLL 分配,必须 fsChannelFreeImageProcResult 释放
                                  // 服务端落盘 / option.returnImage=false 时为 NULL
    char*    resultJson;          // 落盘模式下含 savedPath/savedRows/savedCols/savedChans
    char*    errorMsg;            // 失败时填充
    uint64_t queuedUs;            // 入队等待时间
    uint64_t computeUs;           // 服务端实际计算时间
    uint64_t totalUs;             // 服务端总时间
    int64_t  elapsedMs;
} FSImageProcResultC;

2.2 同步调用模板

cpp 复制代码
#include "fixSharedMemory_api.h"

// 1. 建通道(FIX 必须已运行)
FSChannelHandle ch = fsChannelCreate(nullptr);   // 默认共享内存名 "FIXSharedMemory"
if (!ch) { /* 处理失败 */ }

// 2. 启用接收缓冲(容纳输出图像 + JSON + 余量)
fsChannelEnableImageProcReceiver(ch, 512ULL * 1024 * 1024);

// 3. 配参数
FSImageProcParamsC params{};
params.command    = "filter.sr";
params.paramsJson = R"({"filter.sr.scaleMode":"scale1"})";
params.timeoutMs  = 600000;

// 4. 调用(阻塞)
FSImageProcResultC result{};
int rc = fsChannelSendImageProcAndWait(ch, &params,
    inputBgrBytes, rows, cols, 3,
    FS_IMAGE_C_RGB24,
    static_cast<uint64_t>(cols) * 3,
    &result);

// 5. 用 result.outImage(DLL 分配)

// 6. 释放 + 关闭
fsChannelFreeImageProcResult(&result);
fsChannelDestroy(ch);

2.3 异步调用 + 进度回调

cpp 复制代码
// 注册回调(注册即生效;不注册=不接收对应消息)
fsChannelSetImageProcProgressCallback(ch,
    [](uint32_t requestId, uint32_t stepDone, uint32_t stepTotal,
       const char* message, void*) {
        std::printf("req#%u %u/%u: %s\n", requestId, stepDone, stepTotal, message);
    }, nullptr);

fsChannelSetImageProcCompleteCallback(ch,
    [](uint32_t requestId, const FSImageProcResultC* r, void*) {
        if (r->procStatus == FS_PROC_C_OK) { /* 用 r->outImage */ }
    }, nullptr);

// 发送(立即返回 requestId,0=失败)
uint32_t reqId = fsChannelSendImageProcAsync(ch, &params,
    inputBgrBytes, rows, cols, 3, FS_IMAGE_C_RGB24,
    static_cast<uint64_t>(cols) * 3);

3. 通用 option.* 字段(跨命令共享)

paramsJson 里以 option. 为前缀的字段适用于所有命令,由框架统一解析,不归命令 handler 管。

字段 类型 默认 含义
option.returnImage bool true false = 服务端完全跳过 SHM 图像回传,仅返回 procStatus + resultJson。适合"只要检测结果不要输出图"的场景
option.resultPath string "" 服务端落盘路径。非空时 FIX 用 cv::imwrite 直接写盘,跳过 SHM 回传。优先级高于 FSImageProcParamsC.resultPath 结构体字段

3.1 落盘路径优先级

paramsJson["option.resultPath"] FSImageProcParamsC.resultPath 服务端实际落盘路径
非空 任意 JSON 中的路径
空 / 未设 非空 结构体里的路径
空 / 未设 不落盘(走 SHM 回传)

为什么要双源:结构体字段方便 C 客户端直接用;JSON 字段允许新参数(如 option.resultFormatoption.resultQuality)在不破坏协议的前提下扩展,未来加新落盘选项不必改 FSImageProcParamsC

3.2 落盘成功后的响应

  • r->outImage = NULLr->outRows = outCols = outChannels = 0r->outStride = 0
  • r->procStatus = FS_PROC_C_OK
  • r->resultJson 含:
    json 复制代码
    {
      "savedPath":  "z:/output/foo.jpg",
      "savedRows":  10997,
      "savedCols":  15360,
      "savedChans": 3
    }

客户端不能用 r->outImage != NULL 判断成功——服务端落盘成功后这字段是 NULL。要看 procStatus == FS_PROC_C_OKresultJson.savedPath

3.3 落盘失败的 fallback

cv::imwrite 失败时(路径无权限、磁盘满、扩展名不识别):

option.returnImage fallback
true(默认) 走 SHM 回传,客户端能拿到完整 outImage;resultJson 加 savePathRequested + saveError 标记
false 不 fallback,仅 resultJson 报错

3.4 用法示例

cpp 复制代码
// 方式 A:结构体字段(C 客户端最方便)
FSImageProcParamsC p{};
p.command    = "filter.sr";
p.paramsJson = "{\"filter.sr.scaleMode\":\"scale4\"}";
p.resultPath = "z:/sr_x4.jpg";

// 方式 B:JSON 字段(推荐,便于一次塞所有参数)
p.command    = "filter.sr";
p.paramsJson = "{"
                  "\"filter.sr.scaleMode\":\"scale4\","
                  "\"option.resultPath\":\"z:/sr_x4.jpg\""
               "}";
p.resultPath = nullptr;

// 方式 C:只要 resultJson,不要图、不落盘
p.command    = "filter.sr";
p.paramsJson = "{\"option.returnImage\":false}";

4. filter.sr — FIX 超分辨率

4.1 用途

对 2D 图像做画质增强 / 上采样:

  • scale1:与输入同尺寸的画质增强
  • scale2:×2 上采样快速档(速度更快,视觉质量弱于 scale4 但强于普通插值放大;适合显示用、对极细纹理不敏感的场景)
  • scale3:×3 上采样(输入 W×H → 输出 3W×3H);内部 ×4 模型推理后 INTER_CUBIC 缩到 ×3
  • scale4:×4 上采样(输入 W×H → 输出 4W×4H)

4.2 JSON 参数

字段(必须带 filter.sr. 前缀 类型 默认 含义
filter.sr.scaleMode string "scale4" "scale1"=同尺寸增强;"scale2"=×2 快速档;"scale3"=×3 上采样;"scale4"=×4 上采样
filter.sr.blendRatio float 1.0 Soft↔Hard 混合比例 [0,1];0 = Soft(柔和/去噪),1 = Hard(锐利)。psnrMode=true 时被忽略
filter.sr.psnrMode bool false 自然模式(Natural mode):true = 输出更自然、无锐化伪影,渐变保留好;blendRatio 被忽略
filter.sr.tileSize int 1024 tile 尺寸(≥ 1024;更小的值会被强制提升到 1024)
filter.sr.batchHint int 1 一次处理的 tile 数;服务端内存吃紧时会自动减半到 1

⚠️ 字段名拼写:服务端读 filter.sr.batchHint;写成 batchHint 会拿不到值,掉默认 1。所有 filter.sr.* 字段均带前缀。

psnrMode 与 blendRatio 的关系psnrMode=trueblendRatio 完全失效(不影响输出)。需要 Soft↔Hard 混合时把 psnrMode 留空或设为 false

4.3 调用要点

  • 输入约束channels=3imageType=FS_IMAGE_C_RGB24(实际是 BGR24 字节序)
  • 输入尺寸:任意,无上限。服务端自动切块处理
  • 输出:scale1 同输入尺寸;scale2 = 2×宽 × 2×高;scale4 = 4×宽 × 4×高
  • 接收缓冲:调用前必须 fsChannelEnableImageProcReceiver(ch, N),N 至少容纳 outRows * outStride + 64KB 余量
  • 环境不可用:服务端缺失 SR 推理能力时返回 procStatus = FS_PROC_C_GPU_UNAVAIL

4.4 共享内存预算

场景 输入 输出 共享内存最低 EnableImageProcReceiver 最低
scale1 / 15360×10997 BGR 483 MB 483 MB ≥ 1 GB ≥ 600 MB
scale2 / 15360×10997 BGR 483 MB 1.93 GB ≥ 2.5 GB ≥ 2 GB
scale4 / 15360×10997 BGR 483 MB 7.7 GB ≥ 9 GB ⚠️ ≥ 8 GB
scale1 / 4K (3840×2160) BGR 24 MB 24 MB ≥ 256 MB ≥ 64 MB
scale4 / 4K BGR 24 MB 384 MB ≥ 512 MB ≥ 512 MB

scale4 大图需要客户端先在 fiSettings 调大 sd_EC_SharedMemoryX/Y/Z,详见主 README。

4.5 进度信号

filter.sr 在处理过程中按 tile 发 progress:

复制代码
done = 已完成的 tile 数
total = 总 tile 数 ≈ ⌈rows/tileSize⌉ × ⌈cols/tileSize⌉
message = "SR tile {done}/{total} batch={N}"

15360×10997 / tile=1024 → 16×12 = 192 tiles。

4.6 完整示例

cpp 复制代码
FSImageProcParamsC params{};
params.command = "filter.sr";
params.paramsJson =
    "{\"filter.sr.scaleMode\":\"scale4\","
    " \"filter.sr.blendRatio\":1.0,"
    " \"filter.sr.psnrMode\":false,"     // true = 自然模式(无锐化伪影),blendRatio 被忽略
    " \"filter.sr.tileSize\":1024,"      // ≥1024,更小会被强制提升到 1024
    " \"filter.sr.batchHint\":1}";
params.timeoutMs = 600000;     // 10 分钟,大图必备

FSImageProcResultC result{};
int rc = fsChannelSendImageProcAndWait(ch, &params,
    bgrBytes, /*rows*/ 10997, /*cols*/ 15360, /*channels*/ 3,
    FS_IMAGE_C_RGB24, /*stride*/ 15360 * 3, &result);

if (rc == FS_API_OK && result.procStatus == FS_PROC_C_OK) {
    printf("SR done: %ux%u in %.2fs (compute=%.2fs)\n",
           result.outCols, result.outRows,
           result.totalUs / 1e6, result.computeUs / 1e6);
    // 处理 result.outImage
} else {
    printf("SR failed: rc=%d procStatus=%d msg=%s\n",
           rc, result.procStatus,
           result.errorMsg ? result.errorMsg : "(null)");
}
fsChannelFreeImageProcResult(&result);

4.7 保存耗时参考(输出落盘)

服务端 option.resultPath 路径或客户端 SHM 回传后落盘,最终都走 cv::imwrite(OpenCV 内部按扫描线流式写入)。编码本身是 CPU bound、单线程,速度强烈受输出格式影响。

以 scale4 / 15360×10997 输出(7.7 GB BGR8)为例:

后缀 实际做什么 估算耗时 输出文件大小 适用
.jpg (quality=95) libjpeg 单线程编码 ~25 s ~300-500 MB 默认;视觉无差
.jpg (quality=75) 同上,更激进压缩 ~17 s ~150-250 MB 偶尔可接受
.bmp 无压缩,直接 dump 字节 ~5-7 s 7.7 GB 最快;磁盘空间换速度
.tif (无压缩) 无压缩 + TIFF 元数据 ~5-7 s 7.7 GB 同 BMP,元数据更丰富
.tif (LZW) LZW 单线程压缩 ~30 s+ ~4-5 GB 慢,不推荐
.png libpng + zlib ~60 s+ ~3-5 GB 真实图像压缩比低且很慢,不推荐

4.7.1 用 scale2 间接缩短保存

scale2 输出是 scale4 的 1/4 大小(1.93 GB vs 7.7 GB),所有保存格式的耗时按比例降低 ~4×。组合最优:scaleMode=scale2 + .bmp ≈ 1-2 秒落盘。

4.7.2 服务端 vs 客户端落盘的耗时差别

两条路径都走 cv::imwrite编码耗时本质相同。差别只在 SHM 大数据传回这段:

路径 传输 SHM 大数据 服务端 cv::imwrite 客户端 cv::imwrite
option.resultPath 命中(服务端落盘) 跳过 ~5-25 s(按格式)
默认(SHM 回传 + 客户端落盘) ~5-8 s(7.7 GB 通过 receiver SHM) ~5-25 s(按格式)

scale4 大图想最快,option.resultPath 让服务端直接写盘——免了 SHM 7.7 GB 的来回。


5. filter.sm — Smart Denoising

非局部均值降噪。

字段 类型 默认 含义
filter.sm.h float 3.0 滤波强度,越大越平滑;典型 3~20
filter.sm.templateWindowSize int 7 模板窗口(奇数,自动 +1)
filter.sm.searchWindowSize int 21 搜索窗口(奇数,自动 +1)

支持通道:1ch 走 cv::fastNlMeansDenoising;3/4ch 走 cv::fastNlMeansDenoisingColored(4ch 时 alpha 原样保留)。

cpp 复制代码
params.paramsJson = R"({"filter.sm.h":5.0, "filter.sm.templateWindowSize":7, "filter.sm.searchWindowSize":21})";

6. filter.um — Unsharp Mask

经典锐化(原图 - 高斯模糊高频 → 加权回去)。RGB 经 Lab L 通道处理。

字段 类型 默认 含义
filter.um.radius float 3.0 高斯模糊 σ;典型 0.5~10
filter.um.amount float 0.7 锐化强度;典型 0.3~1.5

7. filter.clahe — CLAHE(限制对比度自适应直方图均衡)

与 W/L 控件 CLAHE 同语义。RGB 经 Lab L 通道处理。

字段 类型 默认 含义
filter.clahe.windowSize int 100 tile 边长(像素),算法内部据此推 tileGridSize = cols / windowSize
filter.clahe.clipLimit float 150.0 对比度限制;典型 4~150
filter.clahe.iterations int 1 迭代次数(重复施加 CLAHE);典型 1,最多 5
filter.clahe.tileGridSize int legacy 兼容字段:仅在没传 windowSize 时启用,按 windowSize = cols / tileGridSize 反推
cpp 复制代码
params.paramsJson = R"({"filter.clahe.windowSize":80, "filter.clahe.clipLimit":40.0, "filter.clahe.iterations":1})";

8. filter.hef — High-Emphasis Filter

频域 DFT + 高斯高通 + 直方图均衡。结果是 8U 单通道;彩色图由 applyOnLuminance 包成 Lab L → 回 BGR。

字段 类型 默认 含义
filter.hef.d0 float 60.0 截止频率;典型 10~90
filter.hef.a float 0.5 低频权重 k1;一般 0.5~1.0
filter.hef.b float 1.2 高频权重 k2;一般 0.5~1.5

9. filter.edgeEnhance — 边缘增强

5×5 拉普拉斯类核 + 与原图插值混合。cv::filter2D 直接 per-channel 处理,不经 Lab

字段 类型 默认 含义
filter.edgeEnhance.amount float 1.0 锐化强度 [0, ∞);1.0 ≈ 原 kernel 效果
filter.edgeEnhance.mix float 1.0 与原图混合比 [0, 1];1=全增强,0=全原图

10. filter.anisoDiffusion — 各向异性扩散(Perona-Malik)

保边降噪。RGB 经 Lab L 通道处理。注意:迭代次数高、图像大时较慢(C++ 双层 for 循环)。

字段 类型 默认 含义
filter.anisoDiffusion.iterations int 10 迭代次数 [1, 50];典型 5~30
filter.anisoDiffusion.kappa float 30.0 边缘敏感度 [1, 100]
filter.anisoDiffusion.lambda float 0.25 扩散速率 [0, 0.25](稳定性要求 ≤ 0.25)
filter.anisoDiffusion.option int 1 扩散函数:1 = exp(-(d/k)²),2 = 1/(1+(d/k)²)

11. filter.gamma — Gamma 校正

out = (in/255)^(1/γ) × 255,LUT 实现。RGB 经 Lab L 通道处理。

字段 类型 默认 含义
filter.gamma.gamma float 1.0 γ ∈ [0.1, 5.0];< 1 提亮暗部> 1 压暗
cpp 复制代码
// X-ray 暗部画 BGA 焊点:γ = 0.5
params.paramsJson = R"({"filter.gamma.gamma":0.5})";

12. filter.exposure — 曝光补偿(EV)

out = in × 2^EV,线性乘法 + 饱和。RGB 经 Lab L 通道处理。每 +1 EV 亮度翻倍,−1 EV 减半。

字段 类型 默认 含义
filter.exposure.ev float 0.0 EV stops ∈ [-3.0, +3.0]

13. filter.bc — Brightness + Contrast

经典 Photoshop 亮度+对比度:out = α·(in - 128) + 128 + β = α·in + (128(1-α) + β)。RGB 经 Lab L 通道处理。

字段 类型 默认 含义
filter.bc.brightness float 0.0 β ∈ [-100, +100],加性偏移
filter.bc.contrast float 1.0 α ∈ [0.0, 5.0],乘性增益(1.0 = 不变)

14. filter.shadowHighlight — 暗部提升 / 亮部压缩

参数化 tone curve(LUT):

复制代码
t' = t + sLift · (1-t)² · (1-t)   -- 暗部抬起
       - hComp · t²   · t          -- 亮部压低

RGB 经 Lab L 通道处理。

字段 类型 默认 含义
filter.shadowHighlight.shadowLift float 0.0 [0, 1],提暗部强度(0=不动)
filter.shadowHighlight.highlightCompress float 0.0 [0, 1],压亮部强度(0=不动)

适合 X-ray 板上同时看 BGA 焊点(暗)和金属屏蔽罩(亮)的场景。


15. filter.applyEffect — 一次性复现 FIX W/L 效果

把 FIX 主程序里 Tools → Save Effect to JSON... 保存的 .json 一次性应用到客户端输入图。等价于:W/L 曲线 + 已应用滤镜栈按 UI 中的顺序在服务端跑一遍。

15.1 用途

客户在 FIX UI 里调好曲线 + 一串滤镜(CLAHE → Gamma → UM …)后 Save 出 .json,第三方客户端拿到这个 .json 就能在自己的图像上复现同样的视觉效果,不用自己 parse JSON、不用自己逐个 SHM 命令调。

15.2 JSON 参数(二选一,inline 优先)

字段 类型 含义
filter.applyEffect.jsonInline object 完整 JSON 对象内联(推荐,便于 client 直接构造)
filter.applyEffect.jsonPath string 服务端可读的 .json 文件路径(便利模式:client 知道 FIX 存盘路径时直接传)

15.3 JSON 结构

可读 + 可手写格式,filter 名与 SHM 单 filter 命令名(filter.<name><name> 部分)严格对应;params 是真正的 JSON 对象。

json 复制代码
{
  "version": 1,
  "wlPoints": ["0,0", "127.5,127.5", "255,255"],
  "stack": [
    { "filter": "filter.clahe",    "params": { "windowSize": 80, "clipLimit": 40.0, "iterations": 1 } },
    { "filter": "filter.gamma",    "params": { "gamma": 0.5 } },
    { "filter": "filter.exposure", "params": { "ev": -0.5 } },
    { "filter": "filter.sr",       "params": { "outputScale": 4, "ratio": 1.0, "psnrMode": true, "tileSize": 1024 } }
  ]
}
字段 类型 说明
version int 当前 1,预留
wlPoints string[] W/L 曲线控制点,每点 "x,y"。缺失或 size < 2 时跳过曲线阶段(等价 identity 直通)
stack object[] 滤镜栈,按数组顺序依次应用(index 0 先跑)
stack[i].filter string filter 名(不区分大小写),与 SHM 单 filter 命令名严格一致,见下方对照表
stack[i].params object 参数对象,键 = 参数名,值 = JSON number / bool / string

filter 名称与参数对照表

filter 名 = §1 命令一览里的命令名(带 filter. 前缀)。客户从 SHM 单命令切到 stack 时,只要把命令名搬到这里即可。

filter 参数(键 : 类型)
filter.sr outputScale: 1/2/3/4,ratio: 0.0~1.0,psnrMode: bool,tileSize: int (≥1024);nativeMode 字段会被忽略
filter.sm h: float,templateWindowSize: int 奇数,searchWindowSize: int 奇数
filter.um radius: float,amount: float
filter.clahe windowSize: int,clipLimit: float,iterations: int
filter.hef d0: float,a: float,b: float
filter.edgeEnhance amount: float,mix: 0.0~1.0
filter.anisoDiffusion iterations: int,kappa: float,lambda: 0.0~0.25,option: 1 或 2
filter.gamma gamma: float
filter.exposure ev: -3.0~+3.0
filter.bc brightness: -100~+100,contrast: 0.0~5.0
filter.shadowHighlight shadowLift: 0.0~1.0,highlightCompress: 0.0~1.0

接受的别名:除完整命令名(首选),filter 字段还接受去掉 filter. 前缀的短名("clahe""filter.clahe")和早期大写枚举名("FIXSR""CLAHE"),大小写不敏感。

向后兼容:服务端同时接受旧格式("filter": 4 整数 + "params": ["windowSize=80",...] 字符串数组)。新代码建议用新格式。

15.4 服务端流程

复制代码
input
   ↓
应用 W/L 曲线(wlPoints 缺失则跳过)
   ↓
按 stack 数组顺序,依次应用每个 filter
   ↓
output

filter.sr 字段映射:JSON 里的 outputScale(int 1/2/4)映射成 SHM 的 scaleModeratio 映射成 blendRatiopsnrMode 同名透传;tileSize 同名透传(强制 ≥ 1024,小于该值会被自动提升);nativeMode 字段被忽略。SR 内部的 tileOverlap 固定 32、batchHint 固定 1。

⚠️ filter.sr Fast / Native 差异:W/L UI 的 SR 默认走 Fast preview 模式(视觉略损细节);SHM 通道永远走 Native tile(更细腻)。所以"Save Effect to JSON 后在 SHM 复现"得到的 SR 效果会比 UI Fast 预览更细腻。需要 UI 与 SHM 严格一致时,在 widget 把 SR 模式切到 "Native (tile)" 再 Save。

步骤失败行为:若 stack 中某一步返回空(如 SR 推理失败),该命令报 FS_PROC_C_INTERNAL 并清空 outImage。

入参校验:若 JSON 既无有效 wlPoints(size ≥ 2)也无非空 stack,命令直接报 FS_PROC_C_BAD_PARAMS —— 避免"成功直通什么也没做"的歧义返回。空 {}{ "version": 1 }{ "stack": [] } 都属此类。

15.5 服务端日志

FIX 端 spdlog 记录:

复制代码
[ImageProc.filter.applyEffect] src=inline version=1 wlPts=3 (apply=true) stack[3]: filter.clahe → filter.gamma → filter.um
[ImageProc.filter.applyEffect]   step 1/3 filter=filter.clahe params=windowSize=80,clipLimit=40.0,iterations=1 took 142ms
[ImageProc.filter.applyEffect]   step 2/3 filter=filter.gamma params=gamma=0.5 took 3ms
[ImageProc.filter.applyEffect]   step 3/3 filter=filter.um    params=radius=2.0,amount=0.8 took 18ms

resultJson 额外回写元信息(避免无谓字节);客户端拿到 procStatus == OK 即视为成功。

15.6 进度回调(progress callback)

filter.applyEffect 在每一步开始前和整命令完成时发 progress 信号,让客户端能显示 step-level 进度:

复制代码
progress(0, N, "applyEffect: step 1/N filter.clahe")
progress(1, N, "applyEffect: step 2/N filter.gamma")
...
progress(N, N, "applyEffect: done")

参数:donetotal = stack 长度message"applyEffect: step i/N <filterName>" 格式,<filterName>stack[i].filter 一致。

嵌套:filter.sr 内部还会发自己的 tile 级进度"SR tile X/Y batch=N"),所以 done 数值不严格单调 —— 进入 SR 步骤时 done 会回到 0~tileCount 范围。客户端如果做进度条,建议按 message 前缀判断"applyEffect: step" = 整体进度;"SR tile" = 当前 SR 内部进度。

15.7 客户端示例

方式 A:inline(推荐,最灵活)

cpp 复制代码
FSImageProcParamsC p{};
p.command    = "filter.applyEffect";
p.paramsJson = R"({
  "filter.applyEffect.jsonInline": {
    "version": 1,
    "wlPoints": ["0,0", "127.5,127.5", "255,255"],
    "stack": [
      { "filter": "filter.clahe", "params": { "windowSize": 80, "clipLimit": 40.0, "iterations": 1 } },
      { "filter": "filter.gamma", "params": { "gamma": 0.5 } }
    ]
  }
})";
p.timeoutMs  = 60000;

FSImageProcResultC r{};
int rc = fsChannelSendImageProcAndWait(ch, &p,
    inputBytes, rows, cols, channels,
    FS_IMAGE_C_RGB24,
    static_cast<uint64_t>(cols) * channels,
    &r);

方式 B:jsonPath(client 已知 FIX 存的文件位置)

cpp 复制代码
p.paramsJson = R"({
  "filter.applyEffect.jsonPath": "Z:/effects/teach_2026_05_15.json"
})";

方式 C:从 FIX UI 端直接抓 .json 内容塞进 inline

cpp 复制代码
QFile f("Z:/effects/foo.json");
f.open(QIODevice::ReadOnly);
QJsonDocument doc = QJsonDocument::fromJson(f.readAll());

QJsonObject top;
top["filter.applyEffect.jsonInline"] = doc.object();
QByteArray bytes = QJsonDocument(top).toJson(QJsonDocument::Compact);

p.paramsJson = bytes.constData();

15.8 与单 filter 命令的关系

互补关系:

  • filter.<X> 单命令:参数键风格 SHM-native (filter.sr.scaleMode 等),适合"只跑一次 CLAHE"
  • filter.applyEffect:参数键风格 W/L widget-native (outputScale/ratio/gamma 等),适合"复现整套 UI 效果"

两条路最终调用相同的滤镜实现,结果一致。


16. 错误码

名称 含义 处理建议
0 FS_PROC_C_OK 成功 result.outImage
-100 FS_PROC_C_BAD_COMMAND 命令名错(拼写错或前缀不对) 检查 params.command
-101 FS_PROC_C_BAD_PARAMS JSON 参数解析失败 检查 JSON 语法、字段名前缀
-102 FS_PROC_C_BAD_INPUT 图像类型/通道不支持 转 BGR24 / GRAY8
-103 FS_PROC_C_GPU_UNAVAIL 服务端 SR 推理能力不可用 filter.sr 才会触发;其它命令不应出现此错
-104 FS_PROC_C_OOM 服务端内存耗尽 改用更小的 scaleMode(如 scale2/scale1)
-105 FS_PROC_C_CANCELED 客户端取消 检查取消逻辑
-106 FS_PROC_C_TIMEOUT 超时 提高 timeoutMs
-200 FS_PROC_C_INTERNAL 推理/处理内部错 result.errorMsg

17. 调用流程概览(读者视角)

复制代码
客户端 fsChannelSendImageProcAndWait("filter.<name>", ...)
    │
    │ 共享内存写包 (协议头 + JSON 参数 + 图像字节)
    ▼
服务端入队(FIFO 串行)
    │
    ▼
按 cmd 路由到对应 filter 处理器
    │
    ▼
output → 共享内存回传 / 服务端落盘 → 客户端

相关文档

上一个
FIX 共享内存使用说明 V2
下一个
FIX AXI UDP 通信协议(通用)
最近修改: 2026-05-20Powered by