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:
SkyLi
2026-03-28 20:28:32 +08:00
commit 356a308f9b
10 changed files with 395 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
# 项目根目录(修改为你的实际路径)
PROJECT_ROOT=/path/to/Infrared-ai-inference-service
+53
View File
@@ -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
View File
@@ -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"]
+58
View File
@@ -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"
```
+148
View File
@@ -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` | 可疑 |
+12
View File
@@ -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",
]
+12
View File
@@ -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",
]
View File
+19
View File
@@ -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
View File
@@ -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)