336 lines
7.7 KiB
Markdown
336 lines
7.7 KiB
Markdown
# 图片标注功能 - 前后端数据流验证
|
||
|
||
## ✅ 数据格式匹配验证
|
||
|
||
### 前端发送(PreviewAttachment.tsx)
|
||
```typescript
|
||
const response = await fetch("/api/detect-object", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({
|
||
imageUrl: url, // ✅ 来自 attachment.url (S3 URL)
|
||
clickX, // ✅ 点击位置 X 坐标
|
||
clickY, // ✅ 点击位置 Y 坐标
|
||
imageIndex: imageIndex || 1, // ✅ 图片序号(从 1 开始)
|
||
imageWidth: img.naturalWidth, // ✅ 图片原始宽度
|
||
imageHeight: img.naturalHeight // ✅ 图片原始高度
|
||
}),
|
||
});
|
||
```
|
||
|
||
### 后端接收(app/main.py)
|
||
```python
|
||
class DetectRequest(BaseModel):
|
||
imageUrl: str # ✅ 匹配
|
||
clickX: int # ✅ 匹配
|
||
clickY: int # ✅ 匹配
|
||
imageIndex: int # ✅ 匹配
|
||
imageWidth: int # ✅ 匹配
|
||
imageHeight: int # ✅ 匹配
|
||
```
|
||
|
||
**结论**:✅ 字段名和类型完全匹配!
|
||
|
||
---
|
||
|
||
## 🔍 图片 URL 可访问性验证
|
||
|
||
### 1. 前端图片来源
|
||
用户上传的图片 → `MultimodalInput` → 上传到 S3 → 获得公开 URL → 存储在 `attachment.url`
|
||
|
||
### 2. S3 URL 格式示例
|
||
```
|
||
https://your-bucket.s3.amazonaws.com/uploads/2025/12/xxxxx.jpg
|
||
```
|
||
|
||
### 3. 后端访问方式
|
||
```python
|
||
# florence_service.py line 60
|
||
response = requests.get(image_url, timeout=10)
|
||
image = Image.open(BytesIO(response.content)).convert("RGB")
|
||
```
|
||
|
||
**要求**:
|
||
- ✅ S3 存储桶必须配置公开读取权限
|
||
- ✅ URL 必须是 HTTPS(后端支持)
|
||
- ✅ 图片格式:JPEG/PNG/WebP(PIL 支持)
|
||
|
||
---
|
||
|
||
## 🧪 完整测试用例
|
||
|
||
### 测试 1:基本功能测试
|
||
|
||
**步骤**:
|
||
```bash
|
||
# 1. 确认 API 服务运行正常
|
||
ssh -p 5204 root@156.225.27.52 "curl http://localhost:8002/health"
|
||
# 预期: {"status":"ok","model_loaded":true}
|
||
|
||
# 2. 使用真实图片 URL 测试
|
||
ssh -p 5204 root@156.225.27.52 "
|
||
curl -X POST http://localhost:8002/api/detect-object \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{
|
||
\"imageUrl\": \"https://images.unsplash.com/photo-1523380677598-64d85d015339\",
|
||
\"clickX\": 250,
|
||
\"clickY\": 250,
|
||
\"imageIndex\": 1,
|
||
\"imageWidth\": 500,
|
||
\"imageHeight\": 500
|
||
}'
|
||
"
|
||
```
|
||
|
||
**预期响应**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"description": "一个红色背包",
|
||
"descriptionEn": "a red backpack",
|
||
"confidence": 0.95,
|
||
"imageIndex": 1,
|
||
"formattedText": "📍图1: 一个红色背包"
|
||
},
|
||
"error": null
|
||
}
|
||
```
|
||
|
||
### 测试 2:前端到后端完整流程
|
||
|
||
**前端操作**:
|
||
1. 访问 https://ai.yydd.ai
|
||
2. 选择图片生成模型
|
||
3. 上传一张包含明显物体的图片(如红色背包)
|
||
4. 点击图片预览
|
||
5. 点击"定位标注"按钮(Target 图标)
|
||
6. 点击图片中的背包位置
|
||
|
||
**预期结果**:
|
||
- ✅ 显示 toast: "正在识别物体..."
|
||
- ✅ 0.2-0.3 秒后显示: "识别成功:一个红色背包"
|
||
- ✅ 输入框自动填入: "📍图1: 一个红色背包"
|
||
- ✅ 关闭预览弹窗
|
||
|
||
**验证后端日志**:
|
||
```bash
|
||
pm2 logs florence-api --lines 20
|
||
```
|
||
|
||
应该看到:
|
||
```
|
||
🔍 开始检测: http://your-s3-url/image.jpg at (250, 250)
|
||
📥 下载图片: 1024 KB
|
||
✂️ 裁剪区域: (150, 150, 350, 350)
|
||
🔍 正在识别物体...
|
||
✅ 识别结果: a red backpack
|
||
📍 格式化输出: 📍图1: 一个红色背包
|
||
```
|
||
|
||
### 测试 3:错误处理
|
||
|
||
**测试场景 A - 无效 URL**:
|
||
```json
|
||
{
|
||
"imageUrl": "https://invalid-url.com/image.jpg",
|
||
...
|
||
}
|
||
```
|
||
预期: `{"success": false, "error": "物体识别失败: ..."}`
|
||
|
||
**测试场景 B - 网络超时**:
|
||
前端显示: "识别失败,请检查网络连接"
|
||
|
||
**测试场景 C - 图片太小**:
|
||
点击坐标超出图片范围 → 后端自动调整裁剪区域
|
||
|
||
---
|
||
|
||
## 🔧 潜在问题和解决方案
|
||
|
||
### 问题 1:S3 图片无法访问
|
||
|
||
**症状**:
|
||
- 后端日志: `requests.exceptions.ConnectionError`
|
||
- 前端显示: "识别失败,请检查网络连接"
|
||
|
||
**原因**:
|
||
- S3 存储桶未配置公开读取
|
||
- CORS 配置不正确
|
||
- 图片 URL 已过期(如使用签名 URL)
|
||
|
||
**解决**:
|
||
```bash
|
||
# 检查 S3 URL 是否可访问
|
||
curl -I https://your-bucket.s3.amazonaws.com/uploads/test.jpg
|
||
|
||
# 应该返回 200 OK
|
||
```
|
||
|
||
### 问题 2:CORS 错误
|
||
|
||
**症状**:
|
||
浏览器控制台: `CORS policy: No 'Access-Control-Allow-Origin' header`
|
||
|
||
**原因**:
|
||
后端 CORS 配置不包含前端域名
|
||
|
||
**解决**:
|
||
已在 `app/main.py` 中配置:
|
||
```python
|
||
allow_origins=["https://ai.yydd.ai", "http://localhost:3000"]
|
||
```
|
||
|
||
### 问题 3:Nginx 代理未配置
|
||
|
||
**症状**:
|
||
- 前端请求 `/api/detect-object` → 404 Not Found
|
||
|
||
**原因**:
|
||
Nginx 未将 `/api/detect-object` 代理到后端 8002 端口
|
||
|
||
**解决**:
|
||
按照《部署状态总结.md》步骤 1 配置 Nginx
|
||
|
||
---
|
||
|
||
## 🎯 最终验证清单
|
||
|
||
部署完成后,请按顺序检查:
|
||
|
||
- [ ] **后端健康检查**
|
||
```bash
|
||
curl http://localhost:8002/health
|
||
# ✅ {"status":"ok","model_loaded":true}
|
||
```
|
||
|
||
- [ ] **Nginx 代理生效**
|
||
```bash
|
||
curl https://ai.yydd.ai/api/detect-object -X POST \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"imageUrl":"https://example.com/test.jpg","clickX":100,"clickY":100,"imageIndex":1,"imageWidth":500,"imageHeight":500}'
|
||
# ✅ 不应该返回 404
|
||
```
|
||
|
||
- [ ] **前端上传图片成功**
|
||
- 上传图片 → 获得 S3 URL
|
||
- 在浏览器地址栏直接访问该 URL → 能看到图片
|
||
|
||
- [ ] **标注按钮显示**
|
||
- 点击上传的图片 → 弹窗显示
|
||
- 右上角有"Target"图标按钮
|
||
|
||
- [ ] **完整标注流程**
|
||
- 点击 Target 按钮 → 按钮变蓝色
|
||
- 点击图片物体 → 显示加载动画
|
||
- 0.2-0.3 秒后 → 输入框填入标注文本
|
||
|
||
- [ ] **后端日志正常**
|
||
```bash
|
||
pm2 logs florence-api --lines 20
|
||
# ✅ 看到识别成功的日志
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 性能监控
|
||
|
||
### GPU 使用率监控
|
||
```bash
|
||
watch -n 1 nvidia-smi
|
||
```
|
||
|
||
**正常状态**:
|
||
- 待机: ~1.2GB 显存,0% 使用率
|
||
- 推理中: ~2GB 显存,80-100% 使用率(0.2秒)
|
||
- 推理后: 回落到待机状态
|
||
|
||
### API 响应时间
|
||
```bash
|
||
# 测试 10 次,查看平均响应时间
|
||
for i in {1..10}; do
|
||
time curl -s -X POST http://localhost:8002/api/detect-object \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"imageUrl":"...","clickX":100,"clickY":100,"imageIndex":1,"imageWidth":500,"imageHeight":500}' \
|
||
> /dev/null
|
||
done
|
||
```
|
||
|
||
**预期**:
|
||
- 首次: ~0.3 秒(冷启动)
|
||
- 后续: ~0.15-0.25 秒
|
||
|
||
---
|
||
|
||
## 🆘 故障排查命令
|
||
|
||
### 快速诊断脚本
|
||
```bash
|
||
#!/bin/bash
|
||
echo "=== Florence-2 API 诊断 ==="
|
||
echo ""
|
||
|
||
echo "1. 服务状态:"
|
||
pm2 list | grep florence
|
||
|
||
echo ""
|
||
echo "2. 健康检查:"
|
||
curl -s http://localhost:8002/health
|
||
|
||
echo ""
|
||
echo "3. GPU 状态:"
|
||
nvidia-smi --query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,memory.total --format=csv,noheader
|
||
|
||
echo ""
|
||
echo "4. 最新日志 (最后 5 行):"
|
||
pm2 logs florence-api --lines 5 --nostream
|
||
|
||
echo ""
|
||
echo "5. 端口监听:"
|
||
netstat -tlnp | grep 8002
|
||
|
||
echo ""
|
||
echo "=== 诊断完成 ==="
|
||
```
|
||
|
||
保存为 `diagnose-florence.sh`,运行:
|
||
```bash
|
||
chmod +x diagnose-florence.sh
|
||
./diagnose-florence.sh
|
||
```
|
||
|
||
---
|
||
|
||
## 📞 问题反馈模板
|
||
|
||
如果遇到问题,请提供以下信息:
|
||
|
||
1. **前端错误**:
|
||
- 浏览器控制台截图
|
||
- Network 标签中的请求/响应详情
|
||
|
||
2. **后端日志**:
|
||
```bash
|
||
pm2 logs florence-api --lines 50
|
||
```
|
||
|
||
3. **服务状态**:
|
||
```bash
|
||
pm2 status
|
||
curl http://localhost:8002/health
|
||
```
|
||
|
||
4. **测试图片 URL**:
|
||
- 提供无法识别的图片 URL
|
||
- 点击的坐标位置
|
||
|
||
---
|
||
|
||
**文档版本**: v1.0
|
||
**创建日期**: 2025-12-15
|
||
**最后更新**: 2025-12-15 14:30
|
||
|
||
**✅ 数据流验证结果**:前后端数据格式完全匹配,只需完成 Nginx 配置和前端集成即可正常工作!
|
||
|