filter.* 命令族接口手册本文档专门讲
filter.*命令家族(像素级 2D 图像处理)。协议总览、命令家族分布、错误码表、共享内存配置等通用内容请看
fixSharedMemory_dll_README.md。适用版本:fixSharedMemoryDll v2.0.0+,FIX 主程序 build ≥ 3685。
| 命令 | 用途 | 后端 | GPU 必需 | 输出尺寸 |
|---|---|---|---|---|
filter.sr |
FIX 超分辨率(×1 增强 / ×2 / ×4 上采样) | libtorch(双模型混合,由 blendRatio 控制 Soft↔Hard) |
✅ | scale1 同尺寸;scale2 ×2(快速档);scale4 ×4 |
所有
filter.*命令的输入图像通过共享内存传给服务端,输出图像通过共享内存返回客户端。
并发模型:服务端fiImageProcWorkerFIFO 串行处理所有图像处理请求,无背压。
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;
#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, ¶ms,
inputBgrBytes, rows, cols, 3,
FS_IMAGE_C_RGB24,
static_cast<uint64_t>(cols) * 3,
&result);
// 5. 用 result.outImage(DLL 分配)
// 6. 释放 + 关闭
fsChannelFreeImageProcResult(&result);
fsChannelDestroy(ch);
// 注册回调(注册即生效;不注册=不接收对应消息)
fsChannelSetImageProcProgressCallback(ch,
[](uint32_t reqId, uint32_t done, uint32_t total,
const char* msg, void*) {
std::printf("req#%u %u/%u: %s\n", reqId, done, total, msg);
}, nullptr);
fsChannelSetImageProcCompleteCallback(ch,
[](uint32_t reqId, const FSImageProcResultC* r, void*) {
if (r->procStatus == FS_PROC_C_OK) { /* 用 r->outImage */ }
}, nullptr);
// 发送(立即返回 requestId,0=失败)
uint32_t reqId = fsChannelSendImageProcAsync(ch, ¶ms,
inputBgrBytes, rows, cols, 3, FS_IMAGE_C_RGB24,
static_cast<uint64_t>(cols) * 3);
option.* 字段(跨命令共享)paramsJson 里以 option. 为前缀的字段适用于所有命令,由框架(fiImageProcWorker)解析,不归命令 handler 管。
| 字段 | 类型 | 默认 | 含义 |
|---|---|---|---|
option.returnImage |
bool | true |
false = 服务端完全跳过 SHM 图像回传,仅返回 procStatus + resultJson。适合"只要检测结果不要输出图"的场景 |
option.resultPath |
string | "" |
服务端落盘路径。非空时 FIX 用 cv::imwrite 直接写盘,跳过 SHM 回传。优先级高于 FSImageProcParamsC.resultPath 结构体字段 |
paramsJson["option.resultPath"] |
FSImageProcParamsC.resultPath |
服务端实际落盘路径 |
|---|---|---|
| 非空 | 任意 | JSON 中的路径 |
| 空 / 未设 | 非空 | 结构体里的路径 |
| 空 / 未设 | 空 | 不落盘(走 SHM 回传) |
为什么要双源:结构体字段方便 C 客户端直接用;JSON 字段允许新参数(如 option.resultFormat、option.resultQuality)在不破坏协议的前提下扩展,未来加新落盘选项不必改 FSImageProcParamsC。
r->outImage = NULL,r->outRows = outCols = outChannels = 0,r->outStride = 0r->procStatus = FS_PROC_C_OKr->resultJson 含:
{
"savedPath": "z:/output/foo.jpg",
"savedRows": 10997,
"savedCols": 15360,
"savedChans": 3
}
客户端不能用
r->outImage != NULL判断成功——服务端落盘成功后这字段是 NULL。要看procStatus == FS_PROC_C_OK或resultJson.savedPath。
cv::imwrite 失败时(路径无权限、磁盘满、扩展名不识别):
option.returnImage |
fallback |
|---|---|
true(默认) |
走 SHM 回传,客户端能拿到完整 outImage;resultJson 加 savePathRequested + saveError 标记 |
false |
不 fallback,仅 resultJson 报错 |
// 方式 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}";
filter.sr — FIX 超分辨率通过 FIX 训练的 ×4 SR 模型,对 2D 图像做:
scale1:与输入同尺寸的画质增强(×4 模型推理后内部 INTER_AREA 缩回原尺寸)scale2:×2 上采样快速档(输入先 cv::resize 0.5× → ×4 模型推理 → 输出 2W×2H)
scale4:×4 上采样(输入 W×H → 输出 4W×4H)字段(必须带 filter.sr. 前缀) |
类型 | 默认 | 含义 |
|---|---|---|---|
filter.sr.scaleMode |
string | "scale4" |
"scale1"=同尺寸增强;"scale2"=×2(快速档,先 0.5× 下采样再 ×4 forward,速度 ~4× 快但略损细节);"scale4"=×4 上采样 |
filter.sr.blendRatio |
float | 1.0 | Soft↔Hard 混合比例 [0,1];0 = Soft(柔和/去噪),1 = Hard(锐利) |
filter.sr.tileSize |
int | 1024 | 内部 tile 尺寸(≥64) |
filter.sr.tileOverlap |
int | 32 | tile 重叠像素 |
filter.sr.batchHint |
int | 1 | 一次 forward 堆 N 张 tile(OOM 自动减半到 1) |
⚠️ 字段名拼写:服务端读
filter.sr.batchHint;写成batchHint会拿不到值,掉默认 1。所有filter.sr.*字段均带前缀。
procStatus = FS_PROC_C_GPU_UNAVAIL,无 CPU 降级channels=3,imageType=FS_IMAGE_C_RGB24(实际是 BGR24 字节序)fiSRTiler 自动切块fsChannelEnableImageProcReceiver(ch, N),N 至少容纳 outRows * outStride + 64KB 余量| 场景 | 输入 | 输出 | 共享内存最低 | 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。
filter.sr 在 fiSRTiler 处理过程中发 progress:
done = 已完成的 tile 数
total = 总 tile 数(≈ ⌈rows/(tileSize-2*overlap)⌉ × ⌈cols/(tileSize-2*overlap)⌉)
message = "SR tile {done}/{total} batch={N}"
15360×10997 / tile=1024 / overlap=32 → core=960 → 16×12 = 192 tiles。
FSImageProcParamsC params{};
params.command = "filter.sr";
params.paramsJson =
"{\"filter.sr.scaleMode\":\"scale4\","
" \"filter.sr.blendRatio\":1.0,"
" \"filter.sr.tileSize\":1024,"
" \"filter.sr.tileOverlap\":32,"
" \"filter.sr.batchHint\":1}";
params.timeoutMs = 600000; // 10 分钟,大图必备
FSImageProcResultC result{};
int rc = fsChannelSendImageProcAndWait(ch, ¶ms,
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);
服务端 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 | 真实图像压缩比低且很慢,不推荐 |
scale2 输出是 scale4 的 1/4 大小(1.93 GB vs 7.7 GB),所有保存格式的耗时按比例降低 ~4×。组合最优:scaleMode=scale2 + .bmp ≈ 1-2 秒落盘。
两条路径都走 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 的来回。
WL UI 中的"FIX SR"滤镜 走独立路径(fiWindowLevelWidget::applyFIXSR),不走共享内存通道,不走 fiSRTiler。
但两条路径共享同一个 fiModelManager 单例和同一个 GPU。为防止并发撞 CUDA context:
fiModelManager::inferenceFIXSR_* / _batch 入口由 m_srInferenceMutex 保护| 值 | 名称 | 含义 | 处理建议 |
|---|---|---|---|
| 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 |
GPU 不可用/未授权 | filter.sr 必须 GPU;其它命令不应触发此错 |
| -104 | FS_PROC_C_OOM |
显存或主机内存耗尽 | 减小 tileSize/batchHint |
| -105 | FS_PROC_C_CANCELED |
客户端取消 | 检查取消逻辑 |
| -106 | FS_PROC_C_TIMEOUT |
超时 | 提高 timeoutMs |
| -200 | FS_PROC_C_INTERNAL |
推理/处理内部错 | 看 result.errorMsg |
客户端 fsChannelSendImageProcAndWait("filter.<name>", ...)
│
│ 共享内存写包 (FS_DATA_IMAGE_PROC_REQ + JSON params + image bytes)
▼
fixSharedMemoryManager::processPacket (fiCore)
│
▼
fiTaskScheduler::onSharedImageProcReceived
│ 拷贝图像 + JSON → SharedMemoryTask → 入 m_detectQueue
▼
fiImageProcWorker (独立 QThread,FIFO 串行消费)
│ 解析 JSON / 路由 cmd 前缀
▼
fiImageProcFilter::runFilter("filter.sr", ...)
└── filter.sr → fiSRTiler::process → fiModelManager::inferenceFIXSR_*_batch
│
▼
output → 共享内存写回 / 服务端 cv::imwrite 落盘 → 客户端
fixSharedMemory_dll_README.md — 协议总览、命令家族分布、共享内存配置