app.github.mp4
TauriApp(Rust+React).An image subject extraction tool that integrates traditional image processing methods, deep learning models (custom-trained), and semantic segmentation models (existing U2-Net), while supporting customizable processing workflows and parameters.
一個整合了傳統影像處理方法(Rust標準圖形處理庫)、深度學習模型(自己訓練的)、語意分割模型(現有U2模型),且支援自訂處理工序與參數的影像主體擷取工具。
Clone the repository:
git clone https://github.com/micromimo/RL-Matting-Agent.git
Prepare the assets:
Place the ONNX format models into /src-tauri/target/debug/up
Place the U2Net series models into /src-tauri/target/debug/models
Run the development server:
Navigate to the project root directory and run the following commands in your terminal:
cd RL-Matting-Agent
npm install
npm run tauri dev
-
终端中执行: git clone https://github.com/micromimo/RL-Matting-Agent.git
-
资源准备: 将OONX格式的模型放入/src-tauri/target/debug/_up_,U2系列模型放在/src-tauri/target/debug/models
-
终端中执行:
cd {项目根目录}
npm install
npm run tauri dev
RL Matting Agent 是一个基于强化学习(Reinforcement Learning)与传统图像处理技术的智能抠图桌面应用。项目以桌面端应用形式交付,集成了 RL Agent 决策(基于弱监督序列补丁决策的图像主体提取)、U²-Net / 轻量级语义分割模型(Rembg)、以及 传统数字图像处理 三套可自定义的抠图方案,通过可视化界面供用户进行参数调节、步骤观察和实时结果对比。
其中,我们自己主要实现的是**基于弱监督序列补丁决策的图像主体提取,**rembg和传统图像处理方案均是集成了现有的开源Rust Create。
| 技术 | 版本 | 用途 |
|---|---|---|
| React | 18.3+ | 前端 UI 框架,组件化开发 |
| TypeScript | 5.4+ | 前端类型安全 |
| Vite | 5.3+ | 前端构建工具,支持 HMR |
| Tailwind CSS | 3.4+ | CSS 原子化样式工具 |
| @tauri-apps/api | 2.0+ | Tauri 前端桥接 API |
| @tauri-apps/plugin-dialog | 2.0+ | 文件选择对话框 |
| 技术 | 版本 | 用途 |
|---|---|---|
| Tauri | 2.x | 跨平台桌面应用框架(WebView + Rust) |
| Rust | Edition 2021 | 后端系统级编程语言 |
| ort (ONNX Runtime) | 2.0.0-rc.12 | ONNX 模型推理引擎(核心) |
| image | 0.25 | 图像编解码与基础变换(resize, crop 等) |
| imageproc | 0.25 | 传统图像处理算子库(Canny、Morphology、AdaptiveThreshold、DistanceTransform、BilateralFilter、ConnectedComponents 等) |
| ndarray | 0.17 | 多维数组运算(与 ONNX Runtime 配合) |
| rayon | 1.10 | 数据并行处理(多线程加速 crop 等操作) |
| base64 | 0.22 | Base64 编码(图像数据传输) |
| serde / serde_json | 1.0 | 序列化 / 反序列化(前后端通信) |
本项目实现了三方案融合的抠图系统,其中两个子方案基于开源生态:
- imgly/background-removal-rs (方案 B 的实现参考)
- 项目地址:
https://github.com/imgly/background-removal-rs - 作用:Rust 版的 AI 背景移除库,集成了多种轻量级语义分割模型(U²-Net, ISNet, Silueta 等)
- 集成方式:因版本兼容性问题(与
ort 2.0协同困难),项目未直接引用该 crate,而是参考其架构,自行基于ort实现了等价的 Rembg Processor。在代码和 UI 中仍使用 "Rembg" 命名以指代这一 AI 背景移除方案。
- 项目地址:
- imageproc (方案 C 的依赖)
- 项目地址:
https://github.com/image-rs/imageproc - 作用:
imagecrate 生态的经典图像处理扩展库 - 集成方式:直接作为核心依赖使用,方案 C 的所有传统图像处理算子均来自此库。
- 项目地址:
| 模型 | 格式 | 输入尺寸 | 用途 |
|---|---|---|---|
| Policy Network (RL Agent) | .onnx |
[1, 3, 224, 224] + bbox state [1, 4] |
强化学习决策网络 |
| U²-Net | .onnx |
[1, 3, 320, 320] |
高质量显著性目标分割 |
| U²-Net Human Seg | .onnx |
[1, 3, 320, 320] |
人像分割专用 |
| Silueta | .onnx |
[1, 3, 320, 320] |
轻量级人像分割 |
- MPS / CoreML 加速:
ort依赖启用coremlfeature,自动使用 Metal Performance Shaders 进行 GPU 加速推理 - 多线程推理:ONNX Session 配置
intra_threads = 4
┌─────────────────────────────────────────────────────────────────┐
│ Input Image (RGB) │
└───────────────────────────┬─────────────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ Config Check & Early Return │ ← 根据开关组合选择路径
└───────────────┬───────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────────┐
│ RL Loop │ │ Rembg Only │ │ Traditional │
│ (Step-by- │ │ (Direct │ │ (Direct │
│ Step Env) │ │ Segmentation)│ │ Processing) │
└──────┬──────┘ └──────┬──────┘ └────────┬────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────┐
│ Mask Generation Pipeline │
│ (Score Map + Threshold + Morphology + ...) │
└───────────────────┬─────────────────────────┘
│
▼
Final RGBA Mask (Base64 / PNG)
这是本项目的核心创新部分。RL Agent 被设计成一个**"观察者"**,通过逐步放大和定位来完成抠图任务。
Action Space(7 个离散动作):
0: Move Left 1: Move Right
2: Move Up 3: Move Down
4: Zoom In 5: Zoom Out
6: Trigger (结束 / 完成)
State Representation(两个输入分支):
- Patch 分支:将当前边界框(Bounding Box)裁剪并 Resize 到
224 × 224RGB,作为图像特征输入 - 几何分支:归一化的边界框状态
[x, y, w, h],均为相对坐标(0~1)
Policy Network 输入 / 输出:
- Input 1:
[1, 3, 224, 224]—— 当前 BBox 的 RGB Patch - Input 2:
[1, 4]—— BBox 归一化状态 - Output 1:
Logits [7]—— 每个动作的得分 - Output 2:
Confidence [1]—— 动作置信度 - Output 3:
Feature Vector [N]—— 中间层特征向量(用于后续 Mask 生成)
推理循环:
- 从全屏 BBox 开始,每一步调用 Policy Network 预测动作
- 依据
max_steps(默认 30)和min_steps_before_trigger(15)约束终止 - 前 15 步强制避免 Trigger 动作(防止过早结束)
- 当 Agent 输出 Trigger 且步数 >= 15 时,调用中心特征提取生成 Mask
基于 U²-Net 系列 ONNX 模型的直接语义分割方案。
处理流程:
- 将目标区域(或全屏)Resize 到模型输入尺寸(320×320)
- RGB 归一化
pixel / 255.0→[1, 3, H, W]Tensor - 送入 ONNX Runtime Session 推理
- 输出 shape
[1, 1, 320, 320]的单通道 Alpha Mask - Resize 回原始尺寸
- 根据阈值(0~1,默认 0.5)生成二值化 / 软 Alpha 通道
支持模型:
| 模型 Key | 文件 | 特点 |
|---|---|---|
u2net |
u2net.onnx |
通用目标分割,质量最好 |
u2net_human_seg |
u2net_human_seg.onnx |
人像专用分割 |
silueta |
silueta.onnx |
轻量级人像分割 |
关键参数:
rembg_threshold:Alpha 阈值,控制前景判定严格度rembg_binary_mode:开启后输出二值化 Mask,关闭则输出软 Alpha
纯图像处理方案,无需深度学习模型,基于 OpenCV 风格的经典算法流水线。
处理步骤:
- 背景色估计:从图像中心区域采样,估计背景 RGB 值
- Score Map 生成:结合 HSV 色彩差异 + 欧氏距离 + 中心先验,计算每个像素的前景置信分数
- 双边滤波(可选):
bilateral_filter保边降噪 - Canny 边缘检测:提取边缘图
- 自适应阈值:大津法(Otsu)或自适应阈值化
- 形态学操作:闭运算 + 开运算,填补孔洞、去除噪点
- 连通域分析:保留最大连通域(
trad_min_component_ratio) - 距离变换(可选):移除边界像素,精细化 Mask
用户可以在 UI 中自由组合三套方案:
| 组合 | 行为 |
|---|---|
| 仅 RL | 完整强化学习推理流程 |
| 仅 Rembg | 直接语义分割(跳过 RL 循环) |
| 仅 Traditional | 直接传统处理(跳过 RL 循环) |
| RL + Rembg | RL 定位 + Rembg 精修 |
| Rembg + Traditional | Rembg 分割 + 传统后处理优化 |
| RL + Traditional | RL 定位 + 传统处理优化 |
| 全开 | RL 定位 → Rembg 精修 → 传统优化 |
| 全关 | 错误提示(至少启用一种) |
注意:当 RL 未启用时(enable_rl_model = false),系统自动跳过 RL 循环,直接根据剩余开关组合调用相应的 Mask 生成路径。
在详细介绍之前,先回答三个核心技术问题:
离线训练(Offline Training):
- 先用数据集训练好一个模型,部署后模型权重不再改变
- 例如:U²-Net 用 DUTS 数据集训练好后,推理时直接使用固定权重
在线 RL 训练(Online Reinforcement Learning):
- 训练过程中,每一步决策都由 Agent 在环境中实时交互产生
- 数据是在训练时生成的,而非提前固定
- 本项目中的实现:
每个 Episode 的流程: ┌─────────────────────────────────────────────┐ │ 1. 从 Dataset 加载 32 张图像(Batch) │ │ 2. 每张图像作为一个"环境" │ │ 3. Agent 从中心 BBox 开始 │ │ 4. 在每张图像上连续执行 15 步动作(Move/Zoom)│ │ 5. 每一步都使用 Policy Network 做决策 │ │ 6. 根据决策结果更新 BBox,计算 Reward │ │ 7. 收集整个 Episode 的轨迹(Trajectory) │ │ 8. 使用 REINFORCE 算法更新 Policy Network │ └─────────────────────────────────────────────┘ - 关键代码在 training.py: run_episode_batch():
# Agent 在环境中逐步决策 for step in range(self.max_steps): # 最多 15 步 logits = model.action_head(fused) # Policy Network 输出 actions = dist.sample() # 采样动作 cx, cy, bw, bh = apply_action(...) # 环境响应 reward = compute_iou_reward(...) # 计算奖励
"弱监督"体现在训练数据的标注方式上:
传统强监督训练:
- 数据需要精确的像素级 Mask 作为 Ground Truth
- 每个像素都有正确答案
本项目的弱监督方式:
- 使用 Open Images 数据集的物体级标注(而非像素级 Mask)
- 训练时加载的
localization.txt包含:图像路径, 分割掩码路径, 忽略区域路径 - 当掩码存在时,使用 IoU Reward;当掩码不存在时,使用启发式 Reward
- 这种方式让模型可以在没有像素级标注的数据上训练
序列补丁决策的含义:
- "补丁"(Patch):每次只关注 BBox 内的局部区域,而非整张图
- "序列"(Sequence):Agent 做连续多步决策,逐步定位目标
- "决策"(Decision):每一步选择 7 个动作中的一个(Move/Zoom/Trigger)
这是 RL 训练的关键设计。本项目使用了混合 Reward 策略:
Case A:有像素级掩码时(IoU Reward)
def _compute_iou_reward(self, bbox, mask_tensor):
# 计算 BBox 与 GT Mask 的 IoU
pred_box = torch.zeros(mask_h, mask_w)
pred_box[y1:y2, x1:x2] = 1.0
intersection = (pred_box * mask).sum()
union = pred_area + mask_area - intersection
iou = intersection / union
return iou # 直接用 IoU 作为 Reward- 当 BBox 越来越贴合目标时,IoU 增大,Reward 变高
- 这是最直接的"正确答案"反馈
Case B:没有像素级掩码时(启发式 Reward)
if mask_batch is None or mask_batch[b] is None:
if action == Trigger:
reward = 0.5 # 提前结束给中等奖励
else:
reward = 0.05 # 每步小奖励- 没有 Ground Truth 时,使用固定规则的稀疏奖励
- Trigger 动作给较高奖励(鼓励 Agent 尽快定位)
- 其他动作给小奖励(鼓励探索)
完整的 Reward 合成公式:
step_reward = base_reward(iou) + trigger_bonus
其中:
base_reward(iou) = {
iou: if mask 存在 # 直接使用 IoU
0.5: if trigger and 无 mask # Trigger 给 0.5
0.05: if 其他 and 无 mask # 普通步骤给 0.05
}
trigger_bonus = 0.2 if action == Trigger else 0
这种设计的核心优势:
- 渐进式学习:即使没有精确标注,Agent 也能学会"何时停止"
- 数据利用最大化:有标注的数据用 IoU 训练,无标注的数据用启发式训练
- 课程学习:先在有标注数据上学习基本定位能力,再在无标注数据上泛化
选择理由:
- 多样性:Open Images 涵盖 600 多个物体类别,涵盖从单细胞生物到人造物体的丰富视觉变化
- 定位标注:OID 提供了 Bounding Box 标注 与 像素级分割掩码(Segmentation Mask),非常适合"强化学习定位 + 精确分割"的训练需求
- 数据规模:足够大的规模支持复杂 RL Agent 的稳定训练
- 社区维护:持续更新,广泛应用于目标检测、分割等 CV 任务的训练
数据集组成:
由于项目体量限制,我们只从庞大的数据集中选取了6000张图像,按类别分层采样(每类最多 50 张),保证类别均衡。
| Split | 图像数量 | 格式 | 标注类型 |
|---|---|---|---|
train |
5,000 | JPG | 类别标签 (class_labels.txt) |
val |
— | JPG | 类别标签 |
test |
1,000 | JPG | 类别标签 + 像素级掩码 (localization.txt) |
图像特点:
- 彩色 RGB 图像,来源于 Google 图像搜索
- 尺寸不固定,训练时统一 Resize 到 224×224
- 背景复杂度高(室内/室外/特殊光照/运动模糊等)
- 物体在画面中的位置、尺度、遮挡程度变化极大,正好模拟 RL Agent 需要处理的复杂场景
目录结构:
dataset/OpenImages/
├── train/
│ ├── 015p6/ # 图像 ID 前缀目录
│ │ ├── 2d10e5e8e8f0764a.jpg
│ │ └── ...
│ └── ...
└── test/
└── ...
metadata/OpenImages/
├── train/
│ ├── class_labels.txt # 图像路径 -> 类别索引 映射
│ └── localization.txt # 图像路径 -> 掩码路径 映射(部分存在)
└── test/
├── class_labels.txt
└── localization.txt # 7,631 条标注(像素级分割掩码)
数据划分策略:
- Training Set:使用
trainsplit 的 5,000 张图像,随机打散后作为 RL Agent 的交互环境 - Validation Set:使用
testsplit 的 1,000 张图像的一部分用于训练中间评估 - 划分依据:遵循 Open Images 官方划分方式,避免数据泄漏
- 数据增强:仅使用
Resize(224,224) + Normalize(ImageNet mean/std)简单处理,因为 RL Agent 需要看到的是原始视觉多样性
在本项目中,val_reward(验证集平均奖励)是评估模型训练效果的最核心指标,它直接决定了最佳模型(policy_best.pt)的保存。
代码位置:training.py: evaluate_model() 与 training.py: main()
# 关键代码:val_reward 是唯一用于保存 best model 的指标
if val_reward > best_reward:
best_reward = val_reward
save_path.parent / "policy_best.pt" # 保存最佳模型val_reward 的计算逻辑:
def evaluate_model(model, val_loader, device):
total_reward = 0.0
total_steps = 0
total_triggers = 0
num_batches = 0
for batch_data in val_loader:
# Agent 在验证集上执行最多 15 步推理
for step in range(15):
actions = torch.argmax(probs) # 使用 argmax,确定性决策
# 计算是否所有样本都 Trigger
if trigger.all():
break
# 每个 Batch 完成后累加统计
batch_reward += 1.0
total_reward += batch_reward
total_steps += step + 1
total_triggers += trigger.sum().item()
num_batches += 1
# 返回三个核心指标
avg_reward = total_reward / max(1, num_batches) # ← 最核心
avg_steps = total_steps / max(1, num_batches) # 辅助指标
avg_triggers = total_triggers / max(1, num_batches) # 辅助指标val_reward 的含义:
- 范围:
[0, 1](每个 Batch 贡献 1.0 的满分) - 本质:完成率 —— 验证集中有多少比例的样本 Agent 能成功完成定位任务
- 解读:
val_reward = 1.0:所有样本 Agent 都能成功定位val_reward = 0.5:一半样本成功定位- 与训练时的
avg_reward不同:训练时是实际 Reward 累加,验证时是二值化的任务完成情况
除了 val_reward,还有两个重要的辅助指标用于诊断 Agent 行为:
| 指标 | 计算方式 | 含义 | 理想值 |
|---|---|---|---|
val_reward |
成功完成的 Batch 比例 | 核心指标 — Agent 定位成功率 | ↑ 越高越好(上限 1.0) |
avg_steps |
平均每个 Episode 的步数 | Agent 效率 — 步数越少越快完成 | ↓ 越低越好(下限由任务难度决定) |
avg_triggers |
Trigger 动作出现的平均次数 | Agent 终结倾向 — 反映是否学会"何时停止" | 适中(过低→不会停止;过高→过早停止) |
训练日志示例:
[Epoch 20/5000] avg_loss=145.6408 avg_reward=2.095 time=7.7s
[VAL] reward=0.875 avg_steps=11.2 triggers=3.4
[NEW BEST] val_reward=0.875, saved to models/policy_best.pt
为什么本项目选择 val_reward(完成率)作为核心指标,而不是传统的 IoU Accuracy?
原因 1:与训练目标对齐
- 训练时 Agent 的目标是"成功定位目标",而非"精确分割"
- RL 训练中的 Reward 本质上就是在优化"能否完成任务"
原因 2:规避 GT Mask 缺失问题
- 验证集中并非所有样本都有像素级 GT Mask
val_reward不需要像素级标注,只需判断 Agent 是否完成了定位流程- 这使得评估可以在更广泛的数据集上进行
原因 3:符合实际应用场景
- 在实际 App 使用中,用户关心的是"能否抠出主体"(成功率)
- 而非"Mask 的 IoU 是多少"(精确但次要)
- 因此用成功率作为核心指标更贴合产品价值
原因 4:稳定可比较
val_reward是[0, 1]范围内的连续值,便于跨训练会话比较- IoU 受图像内容影响大,不同数据集之间可比性差
算法:Actor-Critic 强化学习(REINFORCE with Baseline)
Reward 设计:
- 基础正奖励:每一步 Agent 都会收到
+0.05的小奖励,鼓励有效探索 - Trigger 奖励:Agent 执行 Trigger 动作时额外
+0.2,鼓励快速定位 - IoU 奖励:使用 Intersection over Union 计算当前 BBox 与 GT Mask 的重叠程度
reward_iou = intersection(pred_box, gt_mask) / union(pred_box, gt_mask) - Step 奖励:基于 IoU 的连续奖励(而非稀疏奖励),提供更密集的学习信号
训练 Pipeline:
1. 图像预处理(ImageNet Normalization)
2. 预计算特征(MobileNetV3-Small Backbone)
3. RL 交互循环(最多 15 步 / Episode)
4. 计算 Per-Step Reward(IoU 基础)
5. 折扣回报计算(γ = 0.99)
6. Policy Loss + Value Loss 计算
7. AdamW 优化器更新
8. Learning Rate Cosine Annealing 调度
训练配置:
| 参数 | 值 | 说明 |
|---|---|---|
| Optimizer | AdamW | 权重衰减 1e-5 |
| Learning Rate | 3e-4 | 初始学习率 |
| LR Scheduler | CosineAnnealingLR | T_max=500, eta_min=3e-6 |
| Batch Size | 32 | 每个 Episode 并行 32 张图像 |
| Max Steps / Episode | 8 ~ 15 | Agent 每个 Episode 的最大步数 |
| Total Params | 1,142,184 | 可训练参数 493,720 |
| Epochs | 5,000 | 总训练轮数 |
| Device | MPS (Apple Silicon) | Mac 上使用 MPS 加速 |
| Gradient Clipping | 1.0 | 防止梯度爆炸 |
训练特点:
- 预训练 Backbone:使用 MobileNetV3-Small 预训练权重(ImageNet),冻结前若干层
- 在线 RL 训练:在训练过程中,Agent 与环境实时交互产生轨迹数据,而非离线固定数据集(详见 4.1.0)
- BBox 状态编码:使用连续的归一化坐标(cx, cy, w, h)而非离散网格
- 混合 Reward:IoU Reward(有标注)+ 启发式 Reward(无标注),最大化数据利用效率
PyTorch → ONNX 导出:
torch.onnx.export(
wrapped_model,
(dummy_patch, dummy_bbox), # 双输入
save_path,
input_names=["patch", "bbox_state"],
output_names=["action_logits", "confidence", "feature"],
dynamic_axes={...},
opset_version=17,
)ONNX 模型规格:
| 项目 | 规格 |
|---|---|
| 文件大小 | ~7 MB |
| 输入 | patch [1, 3, 224, 224] + bbox_state [1, 4] |
| 输出 | action_logits [1, 7] + confidence [1, 1] + feature [1, 128] |
| Opset | 17 |
| 推理引擎 | ONNX Runtime (ort 2.0.0-rc.12) |
| 优化级别 | GraphOptimizationLevel::All |
| 线程配置 | 4 线程 |
可用 Checkpoint:
models/
policy_best.pt # 最佳模型
policy_checkpoint_epoch*.pt # 每 10 epoch 保存的 Checkpoint
policy_network.onnx # 最终导出的 ONNX 模型
项目使用公开的 U²-Net 系列预训练权重:
- 由
rembg(Python) /rembg-rs社区维护 - 训练数据:DUTS-TR + DUT-TE + HKU-IS + PASCAL VOC 等显著性检测数据集
- 直接下载 ONNX 格式权重,无需重新训练
// 模型加载
RlEngine::load(model_path)
// → 初始化 ONNX Runtime Session
// → 配置 GraphOptimizationLevel::All + 4 线程
// 推理(双输入模式)
fn infer(&mut self, patch: &[f32], bbox_state: &[f32]) -> Result<(u32, f32)>
// Input: patch [3*224*224] → [1, 3, 224, 224] Tensor
// Input: bbox [4] → [1, 4] Tensor
// Output: argmax(logits[7]), confidence
// 推理(带特征提取模式)
fn infer_with_feature(...) -> Result<(u32, f32, Vec<f32>)>
// 额外输出 Feature Vector,用于 Score Map 计算// 模型动态检测
detect_input_hw(session)
// → 从 ONNX Session 的 Input Shape 自动推断输入尺寸
// → 支持 320x320 / 256x256 等不同模型
// 单 BBox 推理
mask_for_bbox(image, config, bbox)
// 1. 裁剪 BBox 区域
// 2. Resize 到模型输入尺寸
// 3. RGB 归一化 [0,1]
// 4. ONNX 推理
// 5. 输出 Shape 解析(支持 [1,1,H,W] / [1,H,W] / [H,W])
// 6. Resize 回原尺寸
// 7. 阈值化 → 生成二值 MaskScore Map 计算逻辑:
score_map(x, y) = Σ(wi × si) / Σ(wi)
其中:
s_color_hsv = 1 - |ΔH|/60 (色调接近度)
s_color_sat = |ΔS| (饱和度差异)
s_color_val = |ΔV|/255 (明度差异)
s_bg_euclid = √(Σ(Ri-Rbg)²)/441.67 (RGB 欧氏距离)
s_center = 1 - √(dx²+dy²)×2 (中心先验)
w: [2.0, 3.0, 1.0, 0.3, 0.2] (各分量权重)
后处理流水线:
Score Map
→ Normalize (min-max)
→ Bilateral Filter (可选)
→ Canny Edge Detection
→ Adaptive Threshold (Otsu / Block-based)
→ Morphology (闭运算 → 开运算)
→ Connected Components Analysis (保留最大连通域)
→ Distance Transform (可选,边缘精修)
→ Final Binary Mask
- 图像加载与预览
- 支持 JPEG / PNG / BMP 等常见格式
- 图像自适应缩放显示
- 实时进度反馈
- RL 循环可视化
- 逐步展示 Agent 每一步的动作(Move/Zoom/Trigger)
- 实时显示 BBox 位置与大小变化
- 展示 Confidence 曲线
- 步骤进度条
- 参数控制面板(Processing Options)
- 强化学习模型开关 + 参数
- Max Steps(最大步数)
- Confidence Threshold(置信度阈值)
- AI 背景移除开关 + 参数
- 模型选择(U²-Net / Human Seg / Silueta)
- Threshold(分割阈值)
- Binary Mode(二值化模式)
- 传统图像处理开关 + 参数
- Canny Low / High(边缘检测阈值)
- Morphology Radius(形态学半径)
- Min Component Ratio(最小连通域比例)
- Edge Weight(边缘增强权重)
- Adaptive Threshold Block / C(自适应阈值参数)
- Bilateral Filter(双边滤波开关及参数)
- Distance Transform(距离变换开关及权重)
- 强化学习模型开关 + 参数
- 结果输出
- 透明背景 PNG 导出(RGBA 格式)
- Base64 传输与预览
- 多方案结果对比
- Tauri 窗口配置:
decorations: true(原生标题栏)theme: auto(自动深色模式跟随系统)- 支持 macOS / Windows / Linux 跨平台
- 事件通信机制:
// 后端 → 前端 app.emit("rl-step-update", &update) app.emit("rl-pipeline-start", &stages) app.emit("rl-pipeline-stage", &stage) // 前端监听 useRlStepListener() // React Hook
- Pipeline 阶段追踪:
load_image → init_bbox → load_model → rl_inference → generate_mask → complete
rl-matting-app/
├── src/ # React 前端
│ ├── App.tsx # 主应用
│ ├── main.tsx # 入口
│ ├── index.css # Tailwind + 自定义样式
│ ├── components/
│ │ ├── ControlPanel.tsx # 参数控制面板
│ │ ├── ImageCanvas.tsx # 图像预览 + BBox 可视化
│ │ ├── GlassCard.tsx # UI 组件
│ │ └── MetricsChart.tsx # 指标图表
│ └── hooks/
│ └── useRlStepListener.ts # RL 步骤监听 Hook
├── src-tauri/ # Rust 后端
│ ├── src/
│ │ ├── main.rs # Tauri 入口
│ │ ├── lib.rs # 主逻辑:RL Loop + 命令定义
│ │ ├── ml_engine.rs # RL Policy Network 推理引擎
│ │ ├── rembg_processor.rs # Rembg/U²-Net 推理处理器
│ │ └── img_processor.rs # 传统图像处理 + Score Map
│ ├── models/ # ONNX 模型
│ │ ├── u2net.onnx
│ │ ├── u2net_human_seg.onnx
│ │ └── silueta.onnx
│ ├── Cargo.toml # Rust 依赖配置
│ └── tauri.conf.json # Tauri 应用配置
└── models/ # PyTorch 训练 Checkpoint
├── policy_best.pt
└── policy_checkpoint_epoch*.pt
| 模块 | 职责 | 关键类型 |
|---|---|---|
lib.rs |
命令入口、RL 循环编排、前后端通信 | ProcessingConfig, BoundingBox, RlStepUpdate |
ml_engine.rs |
Policy Network 加载与推理 | RlEngine |
rembg_processor.rs |
U²-Net 系列模型加载与推理 | RembgProcessor |
img_processor.rs |
图像加载、裁剪、Score Map、Mask 后处理 | generate_mask(), generate_rembg_only_mask() |
pub struct ProcessingConfig {
enable_rl_model: bool, // 启用强化学习
enable_traditional: bool, // 启用传统处理
enable_rembg: bool, // 启用 AI 背景移除
rl_max_steps: u32, // RL 最大步数
rl_confidence_threshold: f64, // RL 置信度阈值
rembg_model: String, // Rembg 模型名
rembg_threshold: f64, // Rembg 阈值
rembg_binary_mode: bool, // Rembg 二值模式
trad_canny_low/high: f64, // Canny 阈值
trad_morphology_radius: u32, // 形态学半径
// ... 更多参数
}
pub struct BoundingBox {
x: u32, y: u32,
width: u32, height: u32,
}
pub struct RlStepUpdate {
step: u32,
action_taken: String,
bbox: BoundingBox,
confidence: f32,
is_finished: bool,
mask_base64: Option<String>,
}# 安装前端依赖
cd rl-matting-app
npm install
# 启动 Tauri 开发模式(同时启动前端 + Rust)
npm run tauri devnpm run tauri build
# 产物位于 src-tauri/target/release/bundle/| 依赖 | 版本要求 |
|---|---|
| Node.js | 18+ |
| npm | 9+ |
| Rust | 1.70+ |
| 操作系统 | macOS / Windows / Linux |
- 模型输入尺寸固定:U²-Net 系列使用 320×320,大图会被缩放到该尺寸再推理,可能损失细节
- RL 训练数据依赖:Policy Network 需要与实际使用场景匹配的训练数据,迁移性待验证
- 多 GPU / 批量推理:当前为单张顺序推理,未实现批量优化
- 模型格式扩展:可扩展支持 ISNet-General (1024×1024)、SAM (Segment Anything) 等更大模型
- 训练可视化:当前仅支持推理可视化,训练过程可视化可作为未来功能