Initial commit: Infrared Equipment Fault Detection HTTP Service
- Add FastAPI microservice for infrared equipment fault detection - Add dual pyproject.toml: local development and Docker deployment - Add MANUAL_SETUP.md for manual file placement instructions - Add Dockerfile for containerized deployment - Add sample .env.example for PROJECT_ROOT configuration - Configure gitignore for weights, lib, venv, and environment files
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
# 项目根目录(修改为你的实际路径)
|
||||||
|
PROJECT_ROOT=/path/to/Infrared-ai-inference-service
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.egg
|
||||||
|
.pytest_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
.mypy_cache/
|
||||||
|
.tox/
|
||||||
|
cov.xml
|
||||||
|
*.cover
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Model weights
|
||||||
|
weights/
|
||||||
|
*.pt
|
||||||
|
*.pth
|
||||||
|
*.onnx
|
||||||
|
*.ckpt
|
||||||
|
|
||||||
|
# Lib (manually placed)
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.python-version
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# Lock files
|
||||||
|
uv.lock
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Claude
|
||||||
|
.claude/
|
||||||
|
CLAUDE.md
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
tests/
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
FROM python:3.10-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 安装 uv
|
||||||
|
RUN pip install uv
|
||||||
|
|
||||||
|
# 复制本地 whl 文件(预下载)
|
||||||
|
COPY lib/ /app/lib/
|
||||||
|
|
||||||
|
# 复制依赖配置(Docker 专用)
|
||||||
|
COPY pyproject.docker.toml /app/pyproject.toml
|
||||||
|
|
||||||
|
# 安装依赖(包括 infrared-data 从本地 whl)
|
||||||
|
RUN uv pip install --system -r /app/pyproject.toml
|
||||||
|
|
||||||
|
# 复制源码
|
||||||
|
COPY src/ ./src/
|
||||||
|
|
||||||
|
# 复制预下载的权重文件
|
||||||
|
COPY weights/ /app/weights/
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# 手动部署说明
|
||||||
|
|
||||||
|
由于网络限制,权重文件和 whl 包需要手动放置到本地目录。
|
||||||
|
|
||||||
|
## 必需文件
|
||||||
|
|
||||||
|
### 1. whl 包
|
||||||
|
- **文件名**: `infrared_data-0.1.0-py3-none-any.whl`
|
||||||
|
- **存放路径**: `lib/infrared_data-0.1.0-py3-none-any.whl`
|
||||||
|
- **下载地址**: 联系项目维护者获取
|
||||||
|
|
||||||
|
### 2. 模型权重文件
|
||||||
|
- **文件名**: `best.pt`
|
||||||
|
- **存放路径**: `weights/best.pt`
|
||||||
|
- **下载地址**: 联系项目维护者获取
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── lib/
|
||||||
|
│ └── infrared_data-0.1.0-py3-none-any.whl
|
||||||
|
├── weights/
|
||||||
|
│ └── best.pt
|
||||||
|
├── src/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── config.py
|
||||||
|
│ └── main.py
|
||||||
|
├── tests/
|
||||||
|
├── pyproject.toml
|
||||||
|
└── Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
## 安装步骤
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 放置上述文件到对应目录
|
||||||
|
|
||||||
|
# 2. 创建 .env 文件(包含项目路径)
|
||||||
|
# 注意:此文件包含绝对路径,每个开发者需要根据实际路径修改
|
||||||
|
cp .env.example .env # 或手动创建
|
||||||
|
|
||||||
|
# 3. 创建虚拟环境并安装依赖
|
||||||
|
set -a && source .env && uv sync
|
||||||
|
|
||||||
|
# 4. 启动服务
|
||||||
|
set -a && source .env && INFERENCE_DEVICE=cpu uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 健康检查
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
|
||||||
|
# 测试推理
|
||||||
|
curl -X POST http://localhost:8000/infer -F "image=@your_image.jpg"
|
||||||
|
```
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
# Infrared Equipment Fault Detection Service
|
||||||
|
|
||||||
|
红外设备故障检测 HTTP 微服务,基于 `infrared-data` whl 包提供推理接口。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- RESTful API 服务
|
||||||
|
- 支持红外图像故障诊断
|
||||||
|
- 返回检测框、温度特征、故障状态
|
||||||
|
- CPU/GPU 灵活切换
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── lib/ # whl 包(需手动放置)
|
||||||
|
│ └── infrared_data-0.1.0-py3-none-any.whl
|
||||||
|
├── weights/ # 模型权重(需手动放置)
|
||||||
|
│ └── best.pt
|
||||||
|
├── src/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── config.py # 配置
|
||||||
|
│ └── main.py # FastAPI 应用
|
||||||
|
├── tests/
|
||||||
|
│ └── valid/ # 测试图片和结果
|
||||||
|
├── pyproject.toml # 本地依赖配置
|
||||||
|
├── pyproject.docker.toml # Docker 依赖配置
|
||||||
|
├── Dockerfile # Docker 镜像
|
||||||
|
├── MANUAL_SETUP.md # 手动部署说明
|
||||||
|
└── README.md # 本文件
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 手动放置文件
|
||||||
|
|
||||||
|
在部署前,需要手动获取并放置以下文件:
|
||||||
|
|
||||||
|
| 文件 | 存放路径 |
|
||||||
|
|------|----------|
|
||||||
|
| whl 包 | `lib/infrared_data-0.1.0-py3-none-any.whl` |
|
||||||
|
| 模型权重 | `weights/best.pt` |
|
||||||
|
|
||||||
|
详细说明请参考 [MANUAL_SETUP.md](MANUAL_SETUP.md)。
|
||||||
|
|
||||||
|
### 2. 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 启动服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# CPU 模式
|
||||||
|
INFERENCE_DEVICE=cpu uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
|
||||||
|
|
||||||
|
# GPU 模式
|
||||||
|
INFERENCE_DEVICE=cuda:0 uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 健康检查
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
|
||||||
|
# 推理测试
|
||||||
|
curl -X POST http://localhost:8000/infer -F "image=@your_image.jpg"
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 文档
|
||||||
|
|
||||||
|
启动服务后访问: http://localhost:8000/docs
|
||||||
|
|
||||||
|
### POST /infer
|
||||||
|
|
||||||
|
上传红外图像进行故障诊断。
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
- Content-Type: `multipart/form-data`
|
||||||
|
- 字段: `image` (图片文件)
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"image": "array",
|
||||||
|
"detections": [
|
||||||
|
{
|
||||||
|
"bbox": [x1, y1, x2, y2],
|
||||||
|
"bbox_xywh": [cx, cy, w, h],
|
||||||
|
"confidence": 0.94,
|
||||||
|
"class_id": 4,
|
||||||
|
"class_name": "conservator"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faults": [
|
||||||
|
{
|
||||||
|
"temp_max": 255.0,
|
||||||
|
"temp_min": 0.0,
|
||||||
|
"temp_mean": 81.1,
|
||||||
|
"temp_std": 68.3,
|
||||||
|
"temp_median": 57.0,
|
||||||
|
"fault_status": "abnormal",
|
||||||
|
"fault_type": "hotspot"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": {
|
||||||
|
"status": "fault_detected",
|
||||||
|
"detection_count": 3,
|
||||||
|
"abnormal_count": 3,
|
||||||
|
"fault_types": ["hotspot"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### GET /health
|
||||||
|
|
||||||
|
健康检查接口。
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"device": "cpu"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker 部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t infrared-inference .
|
||||||
|
|
||||||
|
# 运行容器
|
||||||
|
docker run -p 8000:8000 infrared-inference
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障类型
|
||||||
|
|
||||||
|
| 类型 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `none` | 正常 |
|
||||||
|
| `hotspot` | 热点异常 |
|
||||||
|
| `local_overheating` | 局部过热 |
|
||||||
|
| `overheat` | 过热 |
|
||||||
|
| `suspect` | 可疑 |
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[project]
|
||||||
|
name = "infrared-inference"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "HTTP microservice for infrared equipment fault detection"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
"fastapi>=0.115.0",
|
||||||
|
"uvicorn[standard]>=0.30.0",
|
||||||
|
"python-multipart>=0.0.12",
|
||||||
|
"aiofiles>=24.0.0",
|
||||||
|
"infrared-data @ file:///app/lib/infrared_data-0.1.0-py3-none-any.whl",
|
||||||
|
]
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[project]
|
||||||
|
name = "infrared-inference"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "HTTP microservice for infrared equipment fault detection"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
"fastapi>=0.115.0",
|
||||||
|
"uvicorn[standard]>=0.30.0",
|
||||||
|
"python-multipart>=0.0.12",
|
||||||
|
"aiofiles>=24.0.0",
|
||||||
|
"infrared-data @ file://${PROJECT_ROOT}/lib/infrared_data-0.1.0-py3-none-any.whl",
|
||||||
|
]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# 权重文件地址
|
||||||
|
WEIGHTS_URL = "http://193.112.94.100:9000/SkyLiCoder/Infrared-ai-research-lab/releases/download/v0.1.0/best.pt"
|
||||||
|
|
||||||
|
# 权重本地路径
|
||||||
|
WEIGHTS_DIR = Path(__file__).parent.parent / "weights"
|
||||||
|
WEIGHTS_PATH = WEIGHTS_DIR / "best.pt"
|
||||||
|
|
||||||
|
# whl 文件地址
|
||||||
|
WHL_URL = "http://193.112.94.100:9000/SkyLiCoder/Infrared-ai-research-lab/releases/download/v0.1.0/infrared_data-0.1.0-py3-none-any.whl"
|
||||||
|
|
||||||
|
# whl 本地路径
|
||||||
|
WHL_DIR = Path(__file__).parent.parent / "lib"
|
||||||
|
WHL_PATH = WHL_DIR / "infrared_data-0.1.0-py3-none-any.whl"
|
||||||
|
|
||||||
|
# 推理设备: "cuda:0" / "cpu"
|
||||||
|
DEVICE = os.getenv("INFERENCE_DEVICE", "cpu")
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
import os
|
||||||
|
import io
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from fastapi import FastAPI, UploadFile, File, HTTPException
|
||||||
|
from PIL import Image
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
from infrared_data import FaultDiagnoser
|
||||||
|
from src.config import WEIGHTS_PATH, DEVICE
|
||||||
|
|
||||||
|
app = FastAPI(title="Infrared Equipment Fault Detection API")
|
||||||
|
|
||||||
|
# 全局诊断器实例
|
||||||
|
_diagnoser: Optional[FaultDiagnoser] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_diagnoser() -> FaultDiagnoser:
|
||||||
|
global _diagnoser
|
||||||
|
if _diagnoser is None:
|
||||||
|
if not WEIGHTS_PATH.exists():
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Weight file not found at {WEIGHTS_PATH}. "
|
||||||
|
"Please run: python scripts/download_assets.py"
|
||||||
|
)
|
||||||
|
_diagnoser = FaultDiagnoser(str(WEIGHTS_PATH))
|
||||||
|
return _diagnoser
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/infer")
|
||||||
|
async def infer(image: UploadFile = File(...)) -> dict:
|
||||||
|
"""
|
||||||
|
接收一张红外图片,返回故障诊断结果(JSON)。
|
||||||
|
|
||||||
|
返回结构:
|
||||||
|
{
|
||||||
|
"image": str,
|
||||||
|
"detections": [...],
|
||||||
|
"faults": [...],
|
||||||
|
"summary": {
|
||||||
|
"status": str,
|
||||||
|
"detection_count": int,
|
||||||
|
"abnormal_count": int,
|
||||||
|
"fault_types": [...]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
# 读取图片内容
|
||||||
|
contents = await image.read()
|
||||||
|
img = Image.open(io.BytesIO(contents)).convert("RGB")
|
||||||
|
img_array = np.array(img)
|
||||||
|
|
||||||
|
diagnoser = get_diagnoser()
|
||||||
|
result = diagnoser.diagnose(img_array, device=DEVICE)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
async def health() -> dict:
|
||||||
|
return {"status": "ok", "device": DEVICE}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||||
Reference in New Issue
Block a user