滑动参数调节面板功能.md 10 KB

滑动参数调节面板功能实现文档

功能概述

在"图像处理"面板(AdvancedProcessingPanel)上添加一个"高级"按钮,点击后打开"滑动参数调节"面板(SliderAdjustmentPanel)。这是一个三级面板,点击返回按钮后会返回到"图像处理"面板。

面板层级结构

OperationPanel (二级面板)
  └── AdvancedProcessingPanel (图像处理 - 三级面板)
        └── SliderAdjustmentPanel (滑动参数调节 - 四级面板)

功能特性

1. 参数调整

  • 增益 (contrast): -5~45,步长0.1
  • 细节 (detail): -0.5~24.5,步长0.1
  • 动态范围 (latitude): -5~20,步长0.1
  • 噪声模式 (noise): 0~20,步长0.1
  • 对比度 (brightness): -8~8,步长0.1(仅前端维护)
  • 亮度 (sharpness): -8~8,步长0.1(仅前端维护)

2. 下拉选择

  • 算法选择: RSymphony(默认)
  • LUT选择: SIGMOID(默认)、LINER 等
  • 风格选择: 均衡、高对比、锐组织、骨骼

3. 实时预览(新增)

  • 滑块调整后自动获取预览图像(500ms防抖)
  • 使用 Blob URL 实现即时预览
  • 仅后端参数触发预览(contrast, detail, latitude, noise)
  • 前端参数调整不触发后端请求

4. 手动操作

  • 重置参数: 重置为当前风格的默认值
  • 保存参数: 永久保存到dcm文件

技术实现

1. 文件结构

src/
├── types/
│   └── imageProcessing.ts                    # 类型定义
├── domain/
│   ├── lutConfig.ts                          # LUT配置
│   └── processingPresets.ts                  # 风格预设配置
├── API/
│   └── imageActions.ts                       # 新增API接口
├── states/
│   ├── panelSwitchSliceForView.ts           # 面板切换状态(已修改)
│   ├── store.ts                              # Redux Store(已修改)
│   └── view/
│       └── sliderAdjustmentPanelSlice.ts    # 滑动参数调节面板状态
└── pages/
    └── view/
        └── components/
            ├── ParameterSlider.tsx           # 参数滑块组件
            ├── SliderAdjustmentPanel.tsx    # 滑动参数调节面板
            ├── AdvancedProcessingPanel.tsx  # 高级处理面板(已修改)
            └── OperationPanel.tsx            # 操作面板(已修改)

2. 核心组件

ParameterSlider 组件

  • 可复用的参数滑块组件
  • 包含:标签、范围提示、当前值显示、滑块、加减按钮
  • 支持自定义范围、步长、禁用状态

SliderAdjustmentPanel 组件

  • 主要面板组件
  • 集成6个参数滑块
  • 集成算法、LUT、风格下拉选择
  • 实现防抖自动保存
  • 提供重置和手动保存按钮

3. 状态管理

sliderAdjustmentPanelSlice

  • 状态:

    • currentImageId: 当前图像ID
    • parameters: 当前参数值
    • selectedStyle: 当前风格
    • selectedAlgorithm: 当前算法
    • selectedLUT: 当前LUT
    • isLoading: 加载状态
    • isSaving: 保存状态
    • isInitialLoad: 初始加载标志
    • error: 错误信息
  • 异步操作:

    • loadImageProcessingParams: 加载图像处理参数
    • saveProcessingParams: 保存图像处理参数
  • 同步操作:

    • setCurrentImageId: 设置当前图像ID
    • updateParameter: 更新单个参数
    • applyPreset: 应用风格预设
    • resetToPreset: 重置为当前风格默认值
    • setAlgorithm: 设置算法
    • setLUT: 设置LUT
    • clearError: 清除错误
    • resetState: 重置状态

panelSwitchSliceForView(修改)

  • 新增 SliderAdjustmentPanel 面板类型
  • 新增 switchToSliderAdjustmentPanel action

4. API接口

getImageProcessingParams

GET /auth/image/{sopInstanceUid}/preparation

获取当前图像处理参数(增益、细节、动态范围、噪声模式)

getProcessedDcm(新增)

GET /auth/image/{sopInstanceUid}/proc?contrast=5.0&detail=9.0&latitude=25.0&noise=12.0

获取应用指定参数后的处理后dcm文件(用于实时预览)

  • 返回: 直接返回dcm文件的二进制数据(Blob)
  • 用途: 滑块调整时实时预览
  • 机制:
    1. 前端调用API获取Blob
    2. 使用 URL.createObjectURL(blob) 创建临时URL
    3. 更新Viewer显示新图像
    4. 适当时机调用 URL.revokeObjectURL() 释放内存

saveImageProcessingParams

POST /auth/image/{sopInstanceUid}/proc
Body: {
  contrast: number,   // 增益
  detail: number,     // 细节
  latitude: number,   // 动态范围
  noise: number       // 噪声模式
}

保存图像处理参数到DICOM文件(永久保存)

  • 用途: 点击"保存参数"按钮时调用
  • 效果: 将处理后的dcm永久保存到文件系统

5. 配置文件

processingPresets.ts

export const PROCESSING_PRESETS: Record<ProcessingStyle, PresetConfig> = {
  '均衡': {
    name: '均衡',
    params: { contrast: 5.0, detail: 9.0, latitude: 25.0, noise: 12.0, brightness: -2.0, sharpness: 1.0 }
  },
  '高对比': {
    name: '高对比',
    params: { contrast: 10.0, detail: 5.0, latitude: 15.0, noise: 8.0, brightness: 0.0, sharpness: 2.0 }
  },
  // ...
};

lutConfig.ts

export const LUT_OPTIONS: LUTType[] = [
  'SIGMOID',
  'LINER',
  // ...
];

用户交互流程

1. 进入滑动参数调节面板

用户在"图像处理"面板 
  → 点击"高级"按钮 
  → 进入"滑动参数调节"面板
  → 自动加载当前图像的参数

2. 调整参数(实时预览)

用户拖动滑块或点击加减按钮
  → 参数值实时更新到Redux
  → 触发500ms防抖定时器
  → 调用GET API获取预览dcm(Blob)
  → 创建Blob URL
  → 刷新Viewer显示

3. 保存参数(永久保存)

用户点击"保存参数"按钮
  → 调用POST API永久保存
  → 成功提示

4. 切换风格

用户选择不同风格
  → 应用对应的预设参数
  → 立即保存到后端(POST)

5. 返回上级面板

用户点击返回按钮
  → 返回到"图像处理"面板

数据流

实时预览流程

用户拖动滑块
  ↓
UI组件 (SliderAdjustmentPanel)
  ↓
Redux Action (updateParameter)
  ↓
Redux State 更新
  ↓
防抖处理 (500ms)
  ↓
API调用 GET /proc (getProcessedDcm)
  ↓
获取Blob数据
  ↓
创建Blob URL
  ↓
更新Viewer显示(TODO)

永久保存流程

用户点击"保存参数"
  ↓
UI组件 (SliderAdjustmentPanel)
  ↓
Redux Thunk (saveProcessingParams)
  ↓
API调用 POST /proc (saveImageProcessingParams)
  ↓
后端永久保存到dcm文件
  ↓
成功提示

注意事项

1. 参数分类

  • 后端参数 (4个): contrast, detail, latitude, noise

    • 会保存到DICOM文件
    • 通过API接口同步
  • 前端参数 (2个): brightness, sharpness

    • 仅在前端维护
    • 不会保存到后端

2. 防抖机制

  • 参数调整触发500ms防抖
  • 避免频繁调用预览API
  • 初始加载时不触发预览
  • 前端参数(brightness, sharpness)不触发后端请求

3. 错误处理

  • API调用失败时显示错误提示
  • 加载失败时使用默认值
  • 错误信息存储在Redux state中

4. 待完善功能

  • 当前图像ID获取逻辑(TODO)
  • 需要从ViewerContainer或其他地方获取当前选中图像的sopInstanceUid

测试步骤

1. 面板切换测试

  • 从"图像处理"面板点击"高级"按钮
  • 验证进入"滑动参数调节"面板
  • 点击返回按钮
  • 验证返回到"图像处理"面板

2. 参数调整测试

  • 拖动各个参数滑块
  • 验证参数值实时更新
  • 验证UI显示正确
  • 等待500ms后验证API调用

3. 风格切换测试

  • 选择不同的风格
  • 验证参数值立即更新
  • 验证立即触发保存

4. 手动操作测试

  • 点击"重置参数"按钮
  • 验证参数恢复到当前风格默认值
  • 点击"保存参数"按钮
  • 验证手动触发保存

5. 边界条件测试

  • 参数值达到最大值/最小值时的表现
  • 网络请求失败时的错误处理
  • 快速切换参数时的防抖效果

潜在问题与解决方案

1. 图像ID获取

问题: 当前代码中sopInstanceUid获取逻辑未实现 解决方案: 需要从ViewerContainer或selectedBodyPosition中获取当前选中图像的ID

2. 参数同步

问题: 前端参数(brightness, sharpness)与后端参数(contrast, detail等)的同步 解决方案:

  • 后端参数通过API同步
  • 前端参数仅在Redux中维护
  • 加载时只更新后端返回的4个参数

3. Blob URL内存管理

问题: 每次预览都创建新的Blob URL,可能导致内存泄漏 解决方案:

  • 在创建新URL前,先revoke旧的URL
  • 组件卸载时清理所有Blob URL
  • 考虑使用useRef存储当前的blobUrl

4. 并发请求

问题: 用户快速切换参数可能导致多次API调用 解决方案: 使用500ms防抖机制,合并多次操作为一次请求

扩展建议

  1. 参数预览: 在调整参数时实时预览效果
  2. 参数历史: 记录参数调整历史,支持撤销/重做
  3. 自定义风格: 允许用户保存自定义的参数组合为新风格
  4. 参数对比: 支持查看调整前后的参数对比
  5. 批量应用: 支持将当前参数应用到多张图像

更新日志

2025-01-22

  • ✅ 完成类型定义
  • ✅ 完成配置文件创建
  • ✅ 完成API接口扩展(包括getProcessedDcm)
  • ✅ 完成状态管理实现
  • ✅ 完成UI组件开发
  • ✅ 完成面板集成
  • ✅ 实现实时预览API调用逻辑
  • ⏳ 待完成:获取当前图像ID逻辑
  • ⏳ 待完成:Cornerstone图像刷新实现
  • ⏳ 待完成:Blob URL内存管理
  • ⏳ 待完成:功能测试

实时预览实现细节

已实现:

  1. 新增 getProcessedDcm API - 获取处理后的dcm Blob
  2. 修改滑块逻辑 - 调用预览API而非保存API
  3. 区分前端参数和后端参数 - 只有后端参数触发预览
  4. 防抖机制 - 500ms延迟避免频繁请求

待实现:

  1. Blob URL → Cornerstone 图像刷新
  2. Blob URL 内存管理(revoke机制)
  3. 获取当前图像ID的完整逻辑