341 lines
8.1 KiB
Markdown
341 lines
8.1 KiB
Markdown
# PLT 裁片处理 API 集成完成
|
||
|
||
## ✅ 已完成的工作
|
||
|
||
### 1. **核心文件创建**
|
||
- ✅ `Server/app/api/v1/algorithm.py` - PLT处理API接口
|
||
- ✅ `Server/pltreader.py` - 已复制到Server目录
|
||
- ✅ `Server/app/main.py` - 已注册algorithm路由
|
||
|
||
### 2. **依赖包更新**
|
||
- ✅ 添加 `scipy` - 用于匈牙利算法匹配
|
||
- ✅ 添加 `Pillow` - 用于图像处理和Base64编码
|
||
- ✅ 已有 `shapely`, `numpy`, `opencv-python-headless`
|
||
|
||
### 3. **API功能特性**
|
||
|
||
#### 核心功能
|
||
1. **PLT文件解析** - 自动识别裁片轮廓
|
||
2. **按尺码分组** - 自动匹配不同尺码的相同裁片
|
||
3. **生成透明PNG** - 每个裁片独立输出,带Alpha通道
|
||
4. **精确坐标计算** - 返回厘米单位的中心点和左上角坐标
|
||
5. **旋转支持** - 可指定0°/90°/-90°/180°旋转
|
||
6. **双文件匹配** - 可上传两个PLT文件进行轮廓对比
|
||
|
||
#### 安全特性
|
||
- ✅ JWT Token 认证保护
|
||
- ✅ 需要登录才能访问
|
||
- ✅ 集成现有用户系统
|
||
|
||
---
|
||
|
||
## 📋 API 接口说明
|
||
|
||
### 接口地址
|
||
```
|
||
POST /api/v1/algorithm/process_plt
|
||
```
|
||
|
||
### 请求方式
|
||
`multipart/form-data`
|
||
|
||
### 请求头
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| `file` | File | **是** | 标准PLT文件 | `standard.plt` |
|
||
| `rotated_file` | File | 否 | 旋转后的PLT文件(用于匹配分析) | `rotated.plt` |
|
||
| `size_labels` | String | **是** | 尺码标签JSON数组 | `["S","M","L","XL","2XL"]` |
|
||
| `dpi` | Integer | 否 | 输出分辨率(默认150) | `150` |
|
||
| `rotation` | Integer | 否 | 旋转角度(0/90/-90/180,默认0) | `90` |
|
||
|
||
### 响应示例
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"total_groups": 5,
|
||
"groups": [
|
||
{
|
||
"group_id": 1,
|
||
"pieces": [
|
||
{
|
||
"size": "S",
|
||
"image_base64": "data:image/png;base64,iVBORw0KGgo...",
|
||
"width_px": 800,
|
||
"height_px": 600,
|
||
"width_cm": 13.54,
|
||
"height_cm": 10.16,
|
||
"center_x_cm": 25.4,
|
||
"center_y_cm": 30.2,
|
||
"left_cm": 18.63,
|
||
"top_cm": 35.28
|
||
},
|
||
{
|
||
"size": "M",
|
||
"image_base64": "data:image/png;base64,iVBORw0KGgo...",
|
||
"width_px": 820,
|
||
"height_px": 615,
|
||
"width_cm": 13.89,
|
||
"height_cm": 10.41,
|
||
"center_x_cm": 26.1,
|
||
"center_y_cm": 30.8,
|
||
"left_cm": 19.15,
|
||
"top_cm": 35.60
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"match_analysis": [
|
||
{
|
||
"size": "S",
|
||
"matches": [
|
||
{
|
||
"standard_id": 0,
|
||
"rotated_id": 3,
|
||
"distance": 0.7032,
|
||
"angle": 0.0
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 测试步骤
|
||
|
||
### 1. 安装依赖
|
||
```bash
|
||
cd Server
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### 2. 启动服务
|
||
```bash
|
||
cd Server
|
||
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||
```
|
||
|
||
### 3. 运行测试脚本
|
||
```bash
|
||
cd Server
|
||
python test_plt_api.py
|
||
```
|
||
|
||
测试脚本会自动:
|
||
1. 登录获取Token
|
||
2. 上传PLT文件进行处理
|
||
3. 显示匹配结果
|
||
|
||
---
|
||
|
||
## 🔧 技术实现细节
|
||
|
||
### 1. **裁片识别算法**
|
||
- 使用 Shapely 进行几何计算
|
||
- 自动构建多边形包含关系树
|
||
- 过滤噪声(面积阈值:0.68%² ~ 80%²)
|
||
|
||
### 2. **尺码匹配算法**
|
||
- **Hausdorff距离** - 衡量轮廓相似度
|
||
- **匈牙利算法** - 最优匹配分配
|
||
- 自动处理旋转(0°/90°/180°/270°)
|
||
- 质心对齐 + 面积归一化
|
||
|
||
### 3. **坐标系统**
|
||
- PLT单位:1016单位 = 1英寸 = 2.54cm
|
||
- 原点:左下角
|
||
- Y轴:向上为正(数学坐标系)
|
||
|
||
### 4. **图像处理**
|
||
- OpenCV绘制裁片轮廓
|
||
- 自动添加Alpha通道(透明背景)
|
||
- Pillow处理旋转和Base64编码
|
||
- DPI元数据写入PNG文件
|
||
|
||
---
|
||
|
||
## 📝 使用示例 (Python)
|
||
|
||
```python
|
||
import requests
|
||
import json
|
||
|
||
# 1. 登录
|
||
login_response = requests.post(
|
||
"http://localhost:8000/api/v1/auth/login",
|
||
json={
|
||
"username": "admin",
|
||
"password": "123456",
|
||
"device_id": "test-device"
|
||
}
|
||
)
|
||
token = login_response.json()["access_token"]
|
||
|
||
# 2. 处理PLT文件
|
||
with open("standard.plt", "rb") as f1:
|
||
files = [
|
||
("file", ("standard.plt", f1, "application/octet-stream"))
|
||
]
|
||
data = {
|
||
"size_labels": json.dumps(["S", "M", "L", "XL", "2XL"]),
|
||
"dpi": 150,
|
||
"rotation": 90 # 顺时针旋转90度
|
||
}
|
||
headers = {"Authorization": f"Bearer {token}"}
|
||
|
||
response = requests.post(
|
||
"http://localhost:8000/api/v1/algorithm/process_plt",
|
||
files=files,
|
||
data=data,
|
||
headers=headers
|
||
)
|
||
|
||
result = response.json()
|
||
print(f"共生成 {result['total_groups']} 组裁片")
|
||
|
||
# 3. 保存图片
|
||
for group in result["groups"]:
|
||
for piece in group["pieces"]:
|
||
# 提取Base64数据
|
||
base64_data = piece["image_base64"].split(",")[1]
|
||
|
||
# 解码并保存
|
||
import base64
|
||
img_data = base64.b64decode(base64_data)
|
||
with open(f"{piece['size']}-{group['group_id']}.png", "wb") as img_file:
|
||
img_file.write(img_data)
|
||
|
||
print(f"已保存: {piece['size']}-{group['group_id']}.png")
|
||
print(f" 位置: ({piece['left_cm']}, {piece['top_cm']}) cm")
|
||
print(f" 尺寸: {piece['width_cm']} x {piece['height_cm']} cm")
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 Photoshop插件集成要点
|
||
|
||
### 1. **创建画布**
|
||
```javascript
|
||
// 根据API返回的尺寸创建画布
|
||
var canvasWidth = 100; // cm,根据实际需求
|
||
var canvasHeight = 150; // cm
|
||
var dpi = 150;
|
||
|
||
var doc = app.documents.add(
|
||
UnitValue(canvasWidth, "cm"),
|
||
UnitValue(canvasHeight, "cm"),
|
||
dpi,
|
||
"PLT裁片",
|
||
NewDocumentMode.RGB,
|
||
DocumentFill.TRANSPARENT
|
||
);
|
||
```
|
||
|
||
### 2. **加载Base64图片**
|
||
```javascript
|
||
function loadBase64Image(base64String, layerName) {
|
||
// 去除前缀
|
||
var base64Data = base64String.split(",")[1];
|
||
|
||
// 保存为临时文件
|
||
var tempFile = new File(Folder.temp + "/temp_piece.png");
|
||
tempFile.encoding = "BINARY";
|
||
tempFile.open("w");
|
||
tempFile.write(decode64(base64Data));
|
||
tempFile.close();
|
||
|
||
// 打开并复制到主文档
|
||
var tempDoc = app.open(tempFile);
|
||
tempDoc.activeLayer.copy();
|
||
app.activeDocument = mainDoc;
|
||
var newLayer = mainDoc.paste();
|
||
newLayer.name = layerName;
|
||
tempDoc.close(SaveOptions.DONOTSAVECHANGES);
|
||
tempFile.remove();
|
||
|
||
return newLayer;
|
||
}
|
||
```
|
||
|
||
### 3. **定位图层**
|
||
```javascript
|
||
function positionLayer(layer, leftCm, topCm, dpi) {
|
||
// 厘米转像素
|
||
var leftPx = leftCm * dpi / 2.54;
|
||
var topPx = topCm * dpi / 2.54;
|
||
|
||
// 移动到指定位置
|
||
var deltaX = leftPx - layer.bounds[0];
|
||
var deltaY = topPx - layer.bounds[1];
|
||
layer.translate(deltaX, deltaY);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
1. **文件编码** - PLT文件必须是文本格式,如果是二进制格式会导致解析失败
|
||
2. **尺码数量** - `size_labels` 的数量必须与PLT文件中的实际尺码数量一致
|
||
3. **内存占用** - 处理大型PLT文件(>1000个裁片)可能需要较长时间
|
||
4. **坐标系** - Photoshop的Y轴向下,如需适配可能需要翻转Y坐标
|
||
|
||
---
|
||
|
||
## 🐛 故障排查
|
||
|
||
### 问题1: 导入错误 `cannot import name 'algorithm'`
|
||
**解决**:
|
||
```bash
|
||
# 确保已重启uvicorn服务
|
||
python -m uvicorn app.main:app --reload
|
||
```
|
||
|
||
### 问题2: `ModuleNotFoundError: No module named 'scipy'`
|
||
**解决**:
|
||
```bash
|
||
pip install scipy Pillow
|
||
```
|
||
|
||
### 问题3: PLT文件解析失败
|
||
**检查**:
|
||
- 文件是否是文本格式(用记事本能打开)
|
||
- 文件编码是否正确(建议UTF-8或GBK)
|
||
- 文件是否包含有效的PLT命令(IN, PU, PD, PA等)
|
||
|
||
---
|
||
|
||
## 📚 相关文档
|
||
|
||
- `Server/docs/API_PLT_Processing.md` - 详细API文档
|
||
- `Server/test_plt_api.py` - 测试示例代码
|
||
- `pltreader.py` - PLT解析器源码
|
||
- `run.py` - 命令行工具示例
|
||
|
||
---
|
||
|
||
## 🎉 完成!
|
||
|
||
现在你可以启动服务器并测试API了:
|
||
|
||
```bash
|
||
cd D:\main\DesignerCEP\Server
|
||
python -m uvicorn app.main:app --reload
|
||
```
|
||
|
||
然后在浏览器访问文档:
|
||
```
|
||
http://localhost:8000/docs
|
||
```
|
||
|
||
祝使用愉快!如有问题请随时反馈。
|
||
|