2026-06-15 15:37:33 +08:00
|
|
|
|
# 图像编辑器设计
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 文档定位
|
|
|
|
|
|
|
|
|
|
|
|
本文档定义合成预览区的实现规则,包括衣服底图显示、印花图层拖动、缩放、旋转、坐标换算、参数同步,以及预览和最终导出保持一致的规则。
|
|
|
|
|
|
|
|
|
|
|
|
后续任何涉及 `image_canvas.py`、印花变换、坐标换算、图片预览或最终合成一致性的任务,都必须阅读本文档。
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 设计目标
|
|
|
|
|
|
|
|
|
|
|
|
- 用户可以在预览区直接拖动、缩放、旋转印花。
|
|
|
|
|
|
- 参数面板和预览区双向同步。
|
|
|
|
|
|
- 预览区缩放不影响真实合成参数。
|
|
|
|
|
|
- 所有合成参数以衣服底图原始像素坐标系保存。
|
|
|
|
|
|
- 最终导出结果与预览中的衣服、印花位置、尺寸、角度一致。
|
|
|
|
|
|
- 图片合成逻辑可以脱离 GUI 单独测试。
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 核心原则
|
|
|
|
|
|
|
|
|
|
|
|
必须遵守:
|
|
|
|
|
|
|
|
|
|
|
|
- Qt 预览负责交互和显示。
|
|
|
|
|
|
- Pillow 负责最终图片合成和导出。
|
|
|
|
|
|
- 禁止截图预览区作为最终导出图片。
|
|
|
|
|
|
- 禁止把屏幕坐标直接保存为合成坐标。
|
|
|
|
|
|
- 禁止把预览缩放比例写入真实合成参数。
|
|
|
|
|
|
- `TransformState` 是唯一可信的印花变换状态。
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 坐标系定义
|
|
|
|
|
|
|
|
|
|
|
|
图像编辑器涉及三套坐标系:
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 屏幕坐标
|
|
|
|
|
|
|
|
|
|
|
|
屏幕坐标是鼠标事件中的窗口坐标或控件坐标。
|
|
|
|
|
|
|
|
|
|
|
|
用途:
|
|
|
|
|
|
|
|
|
|
|
|
- 接收鼠标点击、拖动、滚轮事件。
|
|
|
|
|
|
- 判断用户操作了哪个控制点。
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 屏幕坐标只能作为交互输入。
|
|
|
|
|
|
- 屏幕坐标不能直接用于最终合成。
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 Scene 坐标
|
|
|
|
|
|
|
|
|
|
|
|
Scene 坐标是 `QGraphicsScene` 中的坐标。
|
|
|
|
|
|
|
|
|
|
|
|
用途:
|
|
|
|
|
|
|
|
|
|
|
|
- 显示衣服底图。
|
|
|
|
|
|
- 显示印花图层。
|
|
|
|
|
|
- 显示选中框、缩放手柄和旋转手柄。
|
|
|
|
|
|
|
|
|
|
|
|
推荐规则:
|
|
|
|
|
|
|
|
|
|
|
|
- `QGraphicsScene` 的坐标应尽量与衣服底图原始像素坐标保持一致。
|
|
|
|
|
|
- 衣服底图左上角放在 scene 坐标 `(0, 0)`。
|
|
|
|
|
|
- 衣服底图宽高等于原始图片像素宽高。
|
|
|
|
|
|
- 画布缩放通过 `QGraphicsView` 的 view transform 实现,不修改 scene 中图片真实尺寸。
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 原图像素坐标
|
|
|
|
|
|
|
|
|
|
|
|
原图像素坐标是衣服底图原始图片的像素坐标。
|
|
|
|
|
|
|
|
|
|
|
|
用途:
|
|
|
|
|
|
|
|
|
|
|
|
- 保存印花位置。
|
|
|
|
|
|
- 保存印花尺寸。
|
|
|
|
|
|
- 执行最终 Pillow 合成。
|
|
|
|
|
|
- 保存模板参数。
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
- `TransformState.x` 和 `TransformState.y` 使用原图像素坐标。
|
|
|
|
|
|
- `TransformState.width` 和 `TransformState.height` 使用原图像素尺寸。
|
|
|
|
|
|
- `TransformState.rotation` 使用角度,单位为度。
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 图层结构
|
|
|
|
|
|
|
|
|
|
|
|
预览区使用 `QGraphicsView / QGraphicsScene`。
|
|
|
|
|
|
|
|
|
|
|
|
图层顺序:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
背景棋盘格
|
|
|
|
|
|
衣服底图 Item
|
|
|
|
|
|
印花图片 Item
|
|
|
|
|
|
印花选中框 Item
|
|
|
|
|
|
缩放控制点 Item
|
|
|
|
|
|
旋转控制点 Item
|
|
|
|
|
|
操作提示 Overlay
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
说明:
|
|
|
|
|
|
|
|
|
|
|
|
- 背景棋盘格可以由 view 背景或 scene 背景绘制。
|
|
|
|
|
|
- 衣服底图不可拖动。
|
|
|
|
|
|
- 印花图片可拖动、缩放、旋转。
|
|
|
|
|
|
- 选中框和控制点仅用于交互,不参与最终导出。
|
|
|
|
|
|
- 操作提示仅显示在 UI 中,不参与最终导出。
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 状态模型
|
|
|
|
|
|
|
|
|
|
|
|
印花变换状态使用统一模型表示:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
TransformState
|
|
|
|
|
|
x: float
|
|
|
|
|
|
y: float
|
|
|
|
|
|
width: float
|
|
|
|
|
|
height: float
|
|
|
|
|
|
rotation: float
|
|
|
|
|
|
keep_aspect_ratio: bool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
字段含义:
|
|
|
|
|
|
|
|
|
|
|
|
- `x`:印花未旋转包围盒左上角在衣服原图中的 X 坐标。
|
|
|
|
|
|
- `y`:印花未旋转包围盒左上角在衣服原图中的 Y 坐标。
|
|
|
|
|
|
- `width`:印花缩放后的宽度。
|
|
|
|
|
|
- `height`:印花缩放后的高度。
|
|
|
|
|
|
- `rotation`:围绕印花中心旋转的角度,单位为度。
|
|
|
|
|
|
- `keep_aspect_ratio`:是否锁定宽高比例。
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
- UI 面板、预览区和导出逻辑必须共享同一个 `TransformState`。
|
|
|
|
|
|
- 预览区交互完成后更新 `TransformState`。
|
|
|
|
|
|
- 参数面板输入变化后更新 `TransformState`。
|
|
|
|
|
|
- `TransformState` 变化后统一刷新预览。
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 印花 Item 设计
|
|
|
|
|
|
|
|
|
|
|
|
建议实现自定义印花图层:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
TransformablePrintItem
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
职责:
|
|
|
|
|
|
|
|
|
|
|
|
- 显示印花图片。
|
|
|
|
|
|
- 接收拖动、缩放、旋转交互。
|
|
|
|
|
|
- 绘制或管理选中框。
|
|
|
|
|
|
- 发出变换状态变化信号。
|
|
|
|
|
|
|
|
|
|
|
|
不负责:
|
|
|
|
|
|
|
|
|
|
|
|
- 不负责最终 Pillow 导出。
|
|
|
|
|
|
- 不负责批量任务。
|
|
|
|
|
|
- 不负责读取文件夹。
|
|
|
|
|
|
- 不负责保存模板文件。
|
|
|
|
|
|
|
|
|
|
|
|
## 8. 拖动设计
|
|
|
|
|
|
|
|
|
|
|
|
### 8.1 操作行为
|
|
|
|
|
|
|
|
|
|
|
|
用户按住印花主体区域并拖动,移动印花位置。
|
|
|
|
|
|
|
|
|
|
|
|
要求:
|
|
|
|
|
|
|
|
|
|
|
|
- 拖动过程中实时移动印花。
|
|
|
|
|
|
- 拖动过程中可以实时更新状态,也可以拖动结束后统一提交。
|
|
|
|
|
|
- 拖动结束后必须同步 X/Y 输入框。
|
|
|
|
|
|
- 拖动不改变宽度、高度和旋转角度。
|
|
|
|
|
|
|
|
|
|
|
|
### 8.2 坐标更新
|
|
|
|
|
|
|
|
|
|
|
|
拖动位移应在 scene 坐标中计算。
|
|
|
|
|
|
|
|
|
|
|
|
推荐公式:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
new_x = old_x + delta_scene_x
|
|
|
|
|
|
new_y = old_y + delta_scene_y
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
由于 scene 坐标与原图像素坐标一致,`new_x` 和 `new_y` 可以直接写入 `TransformState`。
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 不强制限制印花必须完全在衣服底图内。
|
|
|
|
|
|
- 导出时只保留衣服画布范围内的内容。
|
|
|
|
|
|
- 如需边界吸附,应作为后续增强功能,不作为第一阶段必需。
|
|
|
|
|
|
|
|
|
|
|
|
## 9. 缩放设计
|
|
|
|
|
|
|
|
|
|
|
|
### 9.1 控制点
|
|
|
|
|
|
|
|
|
|
|
|
选中印花时显示 8 个缩放控制点:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
左上、上中、右上、右中、右下、下中、左下、左中
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
第一阶段至少需要支持四角缩放:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
左上、右上、右下、左下
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 9.2 缩放行为
|
|
|
|
|
|
|
|
|
|
|
|
要求:
|
|
|
|
|
|
|
|
|
|
|
|
- 默认锁定宽高比例。
|
|
|
|
|
|
- 勾选 `锁定宽高比例` 时,拖动四角控制点按原始比例缩放。
|
|
|
|
|
|
- 取消锁定后,可以独立改变宽度和高度。
|
|
|
|
|
|
- 缩放后同步宽度和高度输入框。
|
|
|
|
|
|
- 缩放不改变旋转角度。
|
|
|
|
|
|
|
|
|
|
|
|
### 9.3 最小尺寸
|
|
|
|
|
|
|
|
|
|
|
|
必须设置最小尺寸,避免印花缩放为 0 或负数。
|
|
|
|
|
|
|
|
|
|
|
|
建议:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
min_width = 10 px
|
|
|
|
|
|
min_height = 10 px
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 9.4 缩放中心
|
|
|
|
|
|
|
|
|
|
|
|
第一阶段推荐使用对角固定缩放:
|
|
|
|
|
|
|
|
|
|
|
|
- 拖动右下角时,左上角保持不动。
|
|
|
|
|
|
- 拖动左上角时,右下角保持不动。
|
|
|
|
|
|
- 拖动右上角时,左下角保持不动。
|
|
|
|
|
|
- 拖动左下角时,右上角保持不动。
|
|
|
|
|
|
|
|
|
|
|
|
若实现复杂度过高,可第一阶段使用中心缩放,但必须保证参数和导出一致。
|
|
|
|
|
|
|
|
|
|
|
|
### 9.5 旋转状态下缩放
|
|
|
|
|
|
|
|
|
|
|
|
旋转后的缩放更复杂。第一阶段推荐规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 控制点跟随旋转后的选中框显示。
|
|
|
|
|
|
- 计算缩放时先将鼠标点从 scene 坐标转换到印花本地坐标。
|
|
|
|
|
|
- 在印花本地坐标中计算新的宽高。
|
|
|
|
|
|
- 再更新 `TransformState`。
|
|
|
|
|
|
|
|
|
|
|
|
如果第一阶段暂不实现旋转状态下的精确控制点缩放,必须在实现说明中明确限制,并保证输入框缩放和导出仍然正确。
|
|
|
|
|
|
|
|
|
|
|
|
## 10. 旋转设计
|
|
|
|
|
|
|
|
|
|
|
|
### 10.1 控制点
|
|
|
|
|
|
|
|
|
|
|
|
旋转控制点位于印花选中框顶部中心外侧,通过一条短线连接选中框。
|
|
|
|
|
|
|
|
|
|
|
|
### 10.2 旋转中心
|
|
|
|
|
|
|
|
|
|
|
|
旋转中心为印花缩放后矩形的中心点。
|
|
|
|
|
|
|
|
|
|
|
|
计算:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
center_x = x + width / 2
|
|
|
|
|
|
center_y = y + height / 2
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 10.3 鼠标旋转
|
|
|
|
|
|
|
|
|
|
|
|
用户拖动旋转控制点时,根据鼠标当前位置和中心点计算角度。
|
|
|
|
|
|
|
|
|
|
|
|
推荐公式:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
angle = atan2(mouse_y - center_y, mouse_x - center_x)
|
|
|
|
|
|
rotation = angle_to_degrees(angle) + offset
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`offset` 用于让控制点初始方向和视觉方向一致。
|
|
|
|
|
|
|
|
|
|
|
|
要求:
|
|
|
|
|
|
|
|
|
|
|
|
- 拖动时实时更新预览。
|
|
|
|
|
|
- 旋转结束后同步角度输入框。
|
|
|
|
|
|
- 角度可以为负数。
|
|
|
|
|
|
- 内部可以归一化到 `-180..180` 或 `0..360`,但 UI 表示要一致。
|
|
|
|
|
|
|
|
|
|
|
|
### 10.4 按钮旋转
|
|
|
|
|
|
|
|
|
|
|
|
右侧参数栏包含:
|
|
|
|
|
|
|
|
|
|
|
|
- `左旋 90°`
|
|
|
|
|
|
- `右旋 90°`
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
左旋 90°:rotation = rotation - 90
|
|
|
|
|
|
右旋 90°:rotation = rotation + 90
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
更新后必须刷新预览并同步输入框。
|
|
|
|
|
|
|
|
|
|
|
|
## 11. 参数面板同步
|
|
|
|
|
|
|
|
|
|
|
|
参数面板包含:
|
|
|
|
|
|
|
|
|
|
|
|
- X 坐标。
|
|
|
|
|
|
- Y 坐标。
|
|
|
|
|
|
- 宽度。
|
|
|
|
|
|
- 高度。
|
|
|
|
|
|
- 锁定宽高比例。
|
|
|
|
|
|
- 角度。
|
|
|
|
|
|
|
|
|
|
|
|
同步规则:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
预览区交互 -> 更新 TransformState -> 更新参数面板
|
|
|
|
|
|
参数面板输入 -> 更新 TransformState -> 刷新预览区
|
|
|
|
|
|
模板选择 -> 生成 TransformState -> 刷新预览区和参数面板
|
|
|
|
|
|
队列项选择 -> 加载该项 TransformState -> 刷新预览区和参数面板
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
防循环规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 参数面板程序化更新输入框时,应避免触发重复变更。
|
|
|
|
|
|
- 可以使用 `blockSignals(True/False)` 或内部更新标记。
|
|
|
|
|
|
|
|
|
|
|
|
## 12. 预览缩放
|
|
|
|
|
|
|
|
|
|
|
|
预览区支持画布缩放,例如:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
82%
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 预览缩放只改变 `QGraphicsView` 的显示变换。
|
|
|
|
|
|
- 预览缩放不改变 `TransformState.x/y/width/height`。
|
|
|
|
|
|
- 鼠标事件需要通过 Qt 的坐标映射转换回 scene 坐标。
|
|
|
|
|
|
|
|
|
|
|
|
推荐:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
view.mapToScene(mouse_pos)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 13. 最终导出设计
|
|
|
|
|
|
|
|
|
|
|
|
最终导出由 Pillow 执行,不使用 Qt 截图。
|
|
|
|
|
|
|
|
|
|
|
|
### 13.1 单张合成输入
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
garment_path
|
|
|
|
|
|
print_path
|
|
|
|
|
|
TransformState
|
|
|
|
|
|
ExportOptions
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 13.2 合成步骤
|
|
|
|
|
|
|
|
|
|
|
|
推荐流程:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
读取衣服底图为 RGBA
|
|
|
|
|
|
读取印花图为 RGBA
|
|
|
|
|
|
将印花缩放到 TransformState.width / height
|
|
|
|
|
|
按 TransformState.rotation 围绕中心旋转
|
|
|
|
|
|
计算旋转后图片应粘贴到衣服底图上的位置
|
|
|
|
|
|
使用 alpha_composite 合成
|
|
|
|
|
|
根据 ExportOptions 保存 PNG 或 JPG
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 13.3 旋转后粘贴位置
|
|
|
|
|
|
|
|
|
|
|
|
Pillow 旋转通常会产生新的包围盒。
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
|
|
|
|
|
|
|
|
|
|
|
- `TransformState.x/y/width/height` 表示旋转前矩形。
|
|
|
|
|
|
- 旋转中心为该矩形中心。
|
|
|
|
|
|
- 旋转后图片粘贴位置应保证旋转中心仍落在同一个中心点。
|
|
|
|
|
|
|
|
|
|
|
|
计算:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
center_x = x + width / 2
|
|
|
|
|
|
center_y = y + height / 2
|
|
|
|
|
|
paste_x = center_x - rotated_width / 2
|
|
|
|
|
|
paste_y = center_y - rotated_height / 2
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 13.4 输出格式
|
|
|
|
|
|
|
|
|
|
|
|
PNG:
|
|
|
|
|
|
|
|
|
|
|
|
- 保留 RGBA 或按需求输出不透明图。
|
|
|
|
|
|
|
|
|
|
|
|
JPG:
|
|
|
|
|
|
|
|
|
|
|
|
- JPG 不支持透明通道。
|
|
|
|
|
|
- 保存 JPG 前必须合成到 RGB 背景。
|
|
|
|
|
|
- 默认背景建议使用白色,除非后续有其他需求。
|
|
|
|
|
|
|
|
|
|
|
|
## 14. 预览与导出一致性
|
|
|
|
|
|
|
|
|
|
|
|
必须保证:
|
|
|
|
|
|
|
|
|
|
|
|
- Qt 中印花显示位置来自 `TransformState`。
|
|
|
|
|
|
- Pillow 导出也使用同一个 `TransformState`。
|
|
|
|
|
|
- 两边使用相同的旋转中心。
|
|
|
|
|
|
- 两边使用相同的宽度、高度和角度定义。
|
|
|
|
|
|
- 预览缩放比例不参与导出。
|
|
|
|
|
|
|
|
|
|
|
|
允许存在的差异:
|
|
|
|
|
|
|
|
|
|
|
|
- Qt 和 Pillow 的抗锯齿细节可能略有不同。
|
|
|
|
|
|
- 字节级像素不要求完全一致。
|
|
|
|
|
|
|
|
|
|
|
|
不允许存在的差异:
|
|
|
|
|
|
|
|
|
|
|
|
- 印花明显偏移。
|
|
|
|
|
|
- 印花尺寸明显不同。
|
|
|
|
|
|
- 旋转中心不同。
|
|
|
|
|
|
- 透明区域显示异常。
|
|
|
|
|
|
|
|
|
|
|
|
## 15. 队列项微调
|
|
|
|
|
|
|
|
|
|
|
|
UI 设计稿中存在 `已微调` 状态。
|
|
|
|
|
|
|
|
|
|
|
|
定义:
|
|
|
|
|
|
|
|
|
|
|
|
- 当用户选中队列中的某一项,并手动调整位置、尺寸或旋转后,该队列项标记为 `已微调`。
|
|
|
|
|
|
- `已微调` 队列项应保存自己的 `TransformState`。
|
|
|
|
|
|
- 重新应用模板时,是否覆盖 `已微调` 项需要用户确认或遵循明确规则。
|
|
|
|
|
|
|
|
|
|
|
|
第一阶段推荐规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 当前队列项被手动调整后标记为 `已微调`。
|
|
|
|
|
|
- 批量导出时,已微调项使用自己的 `TransformState`。
|
|
|
|
|
|
- 未微调项使用当前模板生成的 `TransformState`。
|
|
|
|
|
|
|
2026-06-16 10:39:31 +08:00
|
|
|
|
## 16. 低对比组合筛选设计
|
|
|
|
|
|
|
|
|
|
|
|
### 16.1 问题定义
|
|
|
|
|
|
|
|
|
|
|
|
当衣服目标区域颜色和印花主要颜色接近时,用户即使完成合成,也可能看不清印花效果。软件应支持在导出前先筛选出这类组合,帮助用户决定是否跳过、替换印花或调整参数。
|
|
|
|
|
|
|
|
|
|
|
|
该功能是筛选和提示能力,不应自动修改素材,不应直接替用户删除队列项。
|
|
|
|
|
|
|
|
|
|
|
|
### 16.2 分析范围
|
|
|
|
|
|
|
|
|
|
|
|
衣服颜色分析不应使用整张衣服图,而应使用当前印花将要覆盖的衣服区域。
|
|
|
|
|
|
|
|
|
|
|
|
输入:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
garment_path
|
|
|
|
|
|
print_path
|
|
|
|
|
|
TransformState
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
推荐区域:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
garment_region = x, y, width, height
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
印花颜色分析应只统计有效像素:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
alpha > 20
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这样可以避免透明 PNG 的透明区域干扰颜色判断。
|
|
|
|
|
|
|
|
|
|
|
|
### 16.3 第一阶段算法
|
|
|
|
|
|
|
|
|
|
|
|
第一阶段推荐使用简单稳定的组合指标:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
RGB 颜色距离
|
|
|
|
|
|
亮度差
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
示例判断:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
如果 RGB 距离 < 45 且亮度差 < 35
|
|
|
|
|
|
=> 标记为 不明显
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
可见度分级:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
正常
|
|
|
|
|
|
偏低
|
|
|
|
|
|
不明显
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
阈值应集中定义,避免散落在 UI 或批量任务代码中。
|
|
|
|
|
|
|
|
|
|
|
|
### 16.4 更准确的后续算法
|
|
|
|
|
|
|
|
|
|
|
|
后续可以在内存中模拟合成但不保存文件:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
按 TransformState 缩放、旋转印花
|
|
|
|
|
|
将印花在内存中叠加到衣服目标区域
|
|
|
|
|
|
比较合成前后的目标区域差异
|
|
|
|
|
|
如果差异很小,标记为不明显
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这种方式比单纯比较主色更准确,因为它考虑透明度、旋转、图案面积和实际覆盖范围。
|
|
|
|
|
|
|
|
|
|
|
|
### 16.5 队列集成
|
|
|
|
|
|
|
|
|
|
|
|
低对比筛选应发生在队列生成后、批量导出前:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
生成合成队列
|
|
|
|
|
|
-> 对每个队列项计算可见度评分
|
|
|
|
|
|
-> 标记 正常 / 偏低 / 不明显
|
|
|
|
|
|
-> 用户筛选或跳过低对比项
|
|
|
|
|
|
-> 执行批量导出
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
要求:
|
|
|
|
|
|
|
|
|
|
|
|
- 单个组合分析失败不应中断整个队列。
|
|
|
|
|
|
- 分析失败应记录日志,并在队列项中显示可理解状态。
|
|
|
|
|
|
- 用户应能查看被标记为 `偏低` 或 `不明显` 的组合。
|
|
|
|
|
|
- 用户应能决定是否跳过这些组合。
|
|
|
|
|
|
|
|
|
|
|
|
## 17. 边界情况
|
2026-06-15 15:37:33 +08:00
|
|
|
|
|
|
|
|
|
|
必须处理:
|
|
|
|
|
|
|
|
|
|
|
|
- 印花部分超出衣服画布。
|
|
|
|
|
|
- 印花完全超出衣服画布。
|
|
|
|
|
|
- 印花透明 PNG。
|
|
|
|
|
|
- 衣服图和印花图尺寸很大。
|
|
|
|
|
|
- 文件路径包含中文。
|
|
|
|
|
|
- 宽度或高度输入为 0、负数或非数字。
|
|
|
|
|
|
- 旋转角度超过 360 度。
|
2026-06-16 10:39:31 +08:00
|
|
|
|
- 衣服目标区域和印花有效区域颜色接近,导致低对比。
|
|
|
|
|
|
- 印花有效像素过少,无法可靠判断主色。
|
2026-06-15 15:37:33 +08:00
|
|
|
|
|
|
|
|
|
|
处理规则:
|
|
|
|
|
|
|
|
|
|
|
|
- 部分超出画布允许导出,只保留画布内内容。
|
|
|
|
|
|
- 完全超出画布时可以导出空印花效果,但应提示用户确认或标记风险。
|
|
|
|
|
|
- 非法尺寸输入应阻止提交并提示。
|
|
|
|
|
|
- 角度可以归一化显示。
|
2026-06-16 10:39:31 +08:00
|
|
|
|
- 低对比组合应提示或标记,但不自动删除。
|
|
|
|
|
|
- 印花有效像素过少时应标记为无法判断,并记录日志。
|
2026-06-15 15:37:33 +08:00
|
|
|
|
|
2026-06-16 10:39:31 +08:00
|
|
|
|
## 18. 测试建议
|
2026-06-15 15:37:33 +08:00
|
|
|
|
|
|
|
|
|
|
核心测试:
|
|
|
|
|
|
|
|
|
|
|
|
- 未旋转印花合成位置正确。
|
|
|
|
|
|
- 缩放后导出尺寸正确。
|
|
|
|
|
|
- 旋转 90 度后中心不偏移。
|
|
|
|
|
|
- 旋转 -8 度后预览和导出大体一致。
|
|
|
|
|
|
- 印花部分超出画布时不会报错。
|
|
|
|
|
|
- 透明 PNG 不出现黑底或白底。
|
|
|
|
|
|
- 预览缩放到 50% 或 200% 后,拖动仍能得到正确原图坐标。
|
|
|
|
|
|
- 参数面板输入后预览同步。
|
|
|
|
|
|
- 预览拖动后参数面板同步。
|
2026-06-16 10:39:31 +08:00
|
|
|
|
- 白色衣服配浅色印花时能标记为低对比或不明显。
|
|
|
|
|
|
- 深色衣服配深色印花时能标记为低对比或不明显。
|
|
|
|
|
|
- 透明 PNG 的透明区域不参与印花主色判断。
|