服务接口初步完成

This commit is contained in:
haotian 2025-05-16 17:22:50 +08:00
parent f9d35b1ba8
commit 57578f94dc
12 changed files with 7251 additions and 208 deletions

5
app/api/v1/api.py Normal file
View File

@ -0,0 +1,5 @@
from fastapi import APIRouter
from app.api.v1.endpoints import events
api_router = APIRouter()
api_router.include_router(events.router, prefix="/api/v1", tags=["events"])

View File

@ -0,0 +1,79 @@
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.crud.event import event
from app.schemas.event import EventList, EventDetail, EventUpdate, EventQuery
router = APIRouter()
@router.get("/events", response_model=List[EventList])
async def get_events(
db: AsyncSession = Depends(get_db),
start_time: Optional[str] = None,
end_time: Optional[str] = None,
etypeName: Optional[str] = None,
area: Optional[str] = None,
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000)
):
"""
获取事件列表
- 支持时间范围查询
- 支持事件类型和区域筛选
- 支持分页
"""
query = EventQuery(
start_time=start_time,
end_time=end_time,
etypeName=etypeName,
area=area,
skip=skip,
limit=limit
)
events = await event.get_multi_with_query(db, query=query)
return [EventList.model_validate(event) for event in events]
@router.get("/events/{event_id}", response_model=EventDetail)
async def get_event(
event_id: str,
db: AsyncSession = Depends(get_db)
):
"""
获取事件详情
"""
event_obj = await event.get_by_id(db, event_id=event_id)
if not event_obj:
raise HTTPException(status_code=404, detail="事件不存在")
return EventDetail.model_validate(event_obj)
@router.put("/events/{event_id}", response_model=EventDetail)
async def update_event(
event_id: str,
event_in: EventUpdate,
db: AsyncSession = Depends(get_db)
):
"""
更新事件信息
"""
event_obj = await event.update_event(
db,
event_id=event_id,
obj_in=event_in
)
if not event_obj:
raise HTTPException(status_code=404, detail="事件不存在")
return EventDetail.model_validate(event_obj)
@router.delete("/events/{event_id}", response_model=EventDetail)
async def delete_event(
event_id: str,
db: AsyncSession = Depends(get_db)
):
"""
删除事件
"""
event_obj = await event.delete_event(db, event_id=event_id)
if not event_obj:
raise HTTPException(status_code=404, detail="事件不存在")
return EventDetail.model_validate(event_obj)

93
app/crud/event.py Normal file
View File

@ -0,0 +1,93 @@
from typing import List, Optional, Dict, Any
from sqlalchemy import select, and_, or_
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.crud.base import CRUDBase
from app.models.models import Event, Image, Temperature
from app.schemas.event import EventUpdate, EventQuery
class CRUDEvent(CRUDBase[Event, EventUpdate, EventUpdate]):
async def get_by_id(self, db: AsyncSession, *, event_id: str) -> Optional[Event]:
"""根据ID获取事件"""
query = (
select(Event)
.options(
selectinload(Event.images),
selectinload(Event.temperatures)
)
.where(Event.eventId == event_id)
)
result = await db.execute(query)
return result.scalar_one_or_none()
async def get_multi_with_query(
self,
db: AsyncSession,
*,
query: EventQuery
) -> List[Event]:
"""根据查询条件获取事件列表"""
conditions = []
if query.start_time:
conditions.append(Event.insDate >= query.start_time)
if query.end_time:
conditions.append(Event.insDate <= query.end_time)
if query.etypeName:
conditions.append(Event.etypeName == query.etypeName)
if query.area:
conditions.append(Event.area == query.area)
query_stmt = (
select(Event)
.options(
selectinload(Event.images),
selectinload(Event.temperatures)
)
)
if conditions:
query_stmt = query_stmt.where(and_(*conditions))
query_stmt = query_stmt.offset(query.skip).limit(query.limit)
result = await db.execute(query_stmt)
return result.scalars().all()
async def update_event(
self,
db: AsyncSession,
*,
event_id: str,
obj_in: EventUpdate
) -> Optional[Event]:
"""更新事件信息"""
event = await self.get_by_id(db, event_id=event_id)
if not event:
return None
update_data = obj_in.model_dump()
for field, value in update_data.items():
setattr(event, field, value)
# db.add(event)
await db.commit()
await db.refresh(event)
return event
async def delete_event(
self,
db: AsyncSession,
*,
event_id: str
) -> Optional[Event]:
"""删除事件"""
event = await self.get_by_id(db, event_id=event_id)
if not event:
return None
await db.delete(event)
await db.commit()
return event
event = CRUDEvent(Event)

26
app/main.py Normal file
View File

@ -0,0 +1,26 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.v1.api import api_router
from app.core.config import settings
app = FastAPI(
title="温度数据采集系统",
description="温度数据采集系统API接口",
version="1.0.0"
)
# 配置CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 在生产环境中应该设置具体的域名
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
app.include_router(api_router)
@app.get("/")
async def root():
return {"message": "温度数据采集系统API服务正在运行"}

View File

@ -90,6 +90,7 @@ class Temperature(Base):
eventId = Column(String(50), ForeignKey('event.eventId'), nullable=False, comment='关联事件ID')
imageId = Column(BigInteger, ForeignKey('image.imageId'), nullable=False, comment='关联图片ID')
temperature = Column(String(20), nullable=False, comment='温度值')
# status = Column(String(2), comment='温度是否正常')
confidence = Column(String(20), nullable=False, comment='识别置信度')
createTime = Column(DateTime, default=datetime.now, nullable=False, comment='创建时间')

102
app/schemas/event.py Normal file
View File

@ -0,0 +1,102 @@
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, ConfigDict
class ImageBase(BaseModel):
imageUrl: str
localPath: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class TemperatureBase(BaseModel):
temperature: str
confidence: str
createTime: datetime
model_config = ConfigDict(from_attributes=True)
class EventBase(BaseModel):
eventId: str
tenantInfoId: Optional[str] = None
reportEventId: Optional[str] = None
number: Optional[str] = None
name: Optional[str] = None
etypeName: Optional[str] = None
insDate: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class EventList(EventBase):
images: List[ImageBase] = []
temperatures: List[TemperatureBase] = []
model_config = ConfigDict(from_attributes=True)
class EventDetail(EventBase):
eclassify: Optional[str] = None
operationType: Optional[str] = None
etype: Optional[str] = None
enTypeName: Optional[str] = None
hkTypeName: Optional[str] = None
reportStatus: Optional[str] = None
results: Optional[str] = None
insDateShow: Optional[datetime] = None
updDate: Optional[datetime] = None
updDateShow: Optional[datetime] = None
fileType: Optional[str] = None
area: Optional[str] = None
floor: Optional[str] = None
map: Optional[str] = None
staffId: Optional[str] = None
targetUserId: Optional[str] = None
position: Optional[str] = None
actualStaffName: Optional[str] = None
targetStaffName: Optional[str] = None
routeName: Optional[str] = None
phoneAddress: Optional[str] = None
width: Optional[str] = None
height: Optional[str] = None
resolution: Optional[str] = None
originX: Optional[str] = None
originY: Optional[str] = None
robotType: Optional[str] = None
eventFloor: Optional[str] = None
floorName: Optional[str] = None
coordId: Optional[str] = None
coord: Optional[str] = None
coordName: Optional[str] = None
positonName: Optional[str] = None
processingRemark: Optional[str] = None
carId: Optional[str] = None
parkingSpaceType: Optional[str] = None
parkingSpaceNumber: Optional[str] = None
carNumber: Optional[str] = None
eno: Optional[str] = None
instrument: Optional[str] = None
evideo: Optional[str] = None
createTime: Optional[datetime] = None
updateTime: Optional[datetime] = None
images: List[ImageBase] = []
temperatures: List[TemperatureBase] = []
model_config = ConfigDict(from_attributes=True)
class EventUpdate(BaseModel):
number: Optional[str] = None
name: Optional[str] = None
etypeName: Optional[str] = None
area: Optional[str] = None
position: Optional[str] = None
processingRemark: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class EventQuery(BaseModel):
start_time: Optional[datetime] = None
end_time: Optional[datetime] = None
etypeName: Optional[str] = None
area: Optional[str] = None
skip: int = 0
limit: int = 100
model_config = ConfigDict(from_attributes=True)

View File

@ -45,62 +45,40 @@
## 3. 详细设计
### 3.1 数据采集模块
### 3.1 数据同步模块
```python
class DataCollector:
class EventSyncService:
def __init__(self):
self.token_manager = TokenManager()
self.http_client = AsyncHTTPClient()
self.kangda = Kangda()
self.ocr = BadiduOcr()
async def sync_events(self):
"""同步事件数据"""
print("开始同步事件数据...")
async def collect_events(self):
# 获取token
token = await self.token_manager.get_token()
# 获取事件列表
events = await self.fetch_events(token)
# 获取事件详情
for event in events:
await self.process_event(event, token)
```
### 3.2 OCR处理模块
```python
class OCRProcessor:
def __init__(self):
self.ocr = PaddleOCR()
event_list = self.kangda.get_event_list()
if not event_list:
print("获取事件列表失败")
return
async def process_image(self, image_path: str) -> Dict:
# 图片预处理
image = self.preprocess_image(image_path)
# OCR识别
result = self.ocr.ocr(image)
# 提取温度数据
temperature = self.extract_temperature(result)
return temperature
```
### 3.3 数据存储模块
```python
class DatabaseManager:
def __init__(self):
self.engine = create_engine(
'mysql+aiomysql://user:password@localhost:3306/temp_db',
pool_size=5,
max_overflow=10,
pool_timeout=30,
pool_recycle=1800
)
self.session = SessionLocal()
# 获取新事件列表
new_events = await self._get_new_events(event_list)
if not new_events:
print("没有新事件需要同步")
return
async def save_event(self, event_data: Dict):
event = Event(**event_data)
self.session.add(event)
await self.session.commit()
print(f"发现 {len(new_events)} 个新事件")
# 获取事件详情并更新
await self._update_event_details(new_events)
print("事件同步完成
```
### 3.4 API接口模块
### 3.2 API接口模块
```python
@router.get("/temperatures")
@ -113,7 +91,6 @@ async def get_temperatures(
db, start_time, end_time
)
```
## 4. 数据库设计
### 4.1 表结构
@ -136,7 +113,6 @@ ALTER TABLE image ADD INDEX idx_image_event_id (event_id);
ALTER TABLE process_log ADD INDEX idx_log_event_id (event_id);
ALTER TABLE process_log ADD INDEX idx_log_create_time (create_time);
```
### 4.3 数据库配置
```ini
@ -152,7 +128,6 @@ max_overflow = 10
pool_timeout = 30
pool_recycle = 1800
```
## 5. 接口设计
### 5.1 内部接口
@ -309,7 +284,6 @@ pool_recycle = 1800
| |
[Redis集群] [文件存储]
```
### 9.3 MySQL配置建议
```ini
@ -337,7 +311,6 @@ server-id = 1
log-bin = mysql-bin
binlog_format = ROW
```
## 10. 测试方案
### 10.1 单元测试

View File

@ -1,9 +1,11 @@
# 需求:
- 设计一个Python后台服务程序用于自动化采集和处理温度数据
- 通过WebSocket接收外部系统的消息触发
- 支持事件驱动的数据采集和处理流程
# 功能:
- WebSocket服务
- 接收外部系统的消息
- 处理消息并触发相应的数据采集流程
@ -18,6 +20,7 @@
- 支持事件的搜索和过滤
# 系统架构:
- 采用分层架构设计
- 数据采集层负责与第三方API交互
- 业务处理层负责数据处理和OCR识别
@ -25,6 +28,7 @@
- API接口层提供对外服务接口
# 技术选型:
- 开发语言Python 3.8+
- Web框架FastAPI
- 数据库MySQL 8.0+
@ -36,160 +40,91 @@
- 日志loguru
# 具体第三方接口:
- 获取token和refresh接口
- url:
- http://erpapi.concoai.com/basis-api/user/login
- 传递参数:
- Query参数
- cookie_flag: Optional[str] = None
- device_id: Optional[str] = None
- is_login: Optional[str] = None
- lang: Optional[str] = None
- password: Optional[str] = None
- username: Optional[str] = None
- 响应参数: 重点保存 data中的token和refreshtoken
```json
{
"code": "2000",
"message": "成功",
"total": null,
"data": {
"token": "xxx",
"refreshToken": "xxx",
"isLogin": null,
"username": null,
"password": null,
"rolePath": "/index/staff-page"
},
"rows": null
}
```
- 获取列表页接口
- url:
- http://erpapi.concoai.com/robot/event/page
- 传递参数:
- Header 参数
- token
- refreshToken
- Body 参数
```json
{"pageNo": 1, "pageSize": 10000}
```
- 响应参数: 获取rows中 的eventId ,insDate, insDateShow
```json
{
"code": "2000",
"message": "成功",
"total": 1,
"data": null,
"rows": [
{
"eventId": "a462a29d7481495380cd47035b19edc0",
"tenantInfoId": "4fff5d4bcc4b4239941ff077a0da8958",
"reportEventId": null,
"number": "ROB23100098",
"name": "X32305000019",
"eclassify": "2",
"operationType": "2",
"etype": "E000007",
"etypeName": "日常巡检",
"enTypeName": "Routine patrol",
"hkTypeName": "日常巡檢\r",
"reportStatus": "0",
"results": "2",
"insDate": "2025-05-06T16:44:31",
"insDateShow": "2025-05-06 16:44:31",
"updDate": null,
"updDateShow": null,
"fileType": null,
"area": null,
"floor": null,
"map": null,
"staffId": null,
"targetUserId": null,
"position": null,
"actualStaffName": null,
"targetStaffName": "员工1",
"routeName": "test",
"phoneAddress": null,
"width": null,
"height": null,
"resolution": null,
"originX": null,
"originY": null,
"imgList": null,
"robotType": "08",
"eventFloor": null,
"floorName": null,
"coordId": null,
"coord": null,
"coordName": null,
"positonName": "A3",
"processingRemark": null,
"carId": null,
"parkingSpaceType": null,
"parkingSpaceNumber": null,
"carNumber": null,
"eno": null,
"instrument": null,
"evideo": null
}
]
}
```
- 获取事件详情接口
- url:
- http://erpapi.concoai.com/robot/event/{eventId}
- 传递参数:
- 路径变量:
- eventId
- 请求头参数:
- token:
- refreshToken
- 响应参数: 主要获取imgList中的图片url.
```json
{
"code": "2000",
"message": "成功",
"total": null,
"data": {
- 获取token和refresh接口
- url:
- http://erpapi.concoai.com/basis-api/user/login
- 传递参数:
- Query参数
- cookie_flag: Optional[str] = None
- device_id: Optional[str] = None
- is_login: Optional[str] = None
- lang: Optional[str] = None
- password: Optional[str] = None
- username: Optional[str] = None
- 响应参数: 重点保存 data中的token和refreshtoken
```json
{
"code": "2000",
"message": "成功",
"total": null,
"data": {
"token": "xxx",
"refreshToken": "xxx",
"isLogin": null,
"username": null,
"password": null,
"rolePath": "/index/staff-page"
},
"rows": null
}
```
- 获取列表页接口
- url:
- http://erpapi.concoai.com/robot/event/page
- 传递参数:
- Header 参数
- token
- refreshToken
- Body 参数
```json
{"pageNo": 1, "pageSize": 10000}
```
- 响应参数: 获取rows中 的eventId ,insDate, insDateShow
```json
{
"code": "2000",
"message": "成功",
"total": 1,
"data": null,
"rows": [
{
"eventId": "a462a29d7481495380cd47035b19edc0",
"tenantInfoId": "4fff5d4bcc4b4239941ff077a0da8958",
"reportEventId": "bb96f28e14d944c79f44321edca4395f",
"reportEventId": null,
"number": "ROB23100098",
"name": "X32305000019",
"eclassify": "2",
"operationType": "2",
"etype": "E000007",
"etypeName": "日常巡检",
"enTypeName": null,
"hkTypeName": null,
"enTypeName": "Routine patrol",
"hkTypeName": "日常巡檢\r",
"reportStatus": "0",
"results": "2",
"insDate": null,
"insDate": "2025-05-06T16:44:31",
"insDateShow": "2025-05-06 16:44:31",
"updDate": null,
"updDateShow": null,
"fileType": "2",
"area": "区域1",
"floor": "",
"fileType": null,
"area": null,
"floor": null,
"map": null,
"staffId": null,
"targetUserId": null,
"position": "75.104378,90.402679",
"position": null,
"actualStaffName": null,
"targetStaffName": "员工1",
"routeName": "test",
"phoneAddress": "http://file.prod.concoai.com/image/4fff5d4bcc4b4239941ff077a0da8958/4f60fbd391e98327f6ee13df1455f23e.jpg",
"width": "3994.0",
"height": "4816.0",
"resolution": "0.100000",
"originX": "-111.361710",
"originY": " -255.272873",
"imgList": [
"http://file.prod.concoai.com/image/4fff5d4bcc4b4239941ff077a0da8958/168c66b32421d8e8d5bc13a0bbb87a30.jpeg"
],
"phoneAddress": null,
"width": null,
"height": null,
"resolution": null,
"originX": null,
"originY": null,
"imgList": null,
"robotType": "08",
"eventFloor": null,
"floorName": null,
@ -205,54 +140,128 @@
"eno": null,
"instrument": null,
"evideo": null
},
"rows": null
}
```
}
]
}
```
- 获取事件详情接口
- url:
- http://erpapi.concoai.com/robot/event/{eventId}
- 传递参数:
- 路径变量:
- eventId
- 请求头参数:
- token:
- refreshToken
- 响应参数: 主要获取imgList中的图片url.
```json
{
"code": "2000",
"message": "成功",
"total": null,
"data": {
"eventId": "a462a29d7481495380cd47035b19edc0",
"tenantInfoId": "4fff5d4bcc4b4239941ff077a0da8958",
"reportEventId": "bb96f28e14d944c79f44321edca4395f",
"number": "ROB23100098",
"name": "X32305000019",
"eclassify": "2",
"operationType": "2",
"etype": "E000007",
"etypeName": "日常巡检",
"enTypeName": null,
"hkTypeName": null,
"reportStatus": "0",
"results": "2",
"insDate": null,
"insDateShow": "2025-05-06 16:44:31",
"updDate": null,
"updDateShow": null,
"fileType": "2",
"area": "区域1",
"floor": "",
"map": null,
"staffId": null,
"targetUserId": null,
"position": "75.104378,90.402679",
"actualStaffName": null,
"targetStaffName": "员工1",
"routeName": "test",
"phoneAddress": "http://file.prod.concoai.com/image/4fff5d4bcc4b4239941ff077a0da8958/4f60fbd391e98327f6ee13df1455f23e.jpg",
"width": "3994.0",
"height": "4816.0",
"resolution": "0.100000",
"originX": "-111.361710",
"originY": " -255.272873",
"imgList": [
"http://file.prod.concoai.com/image/4fff5d4bcc4b4239941ff077a0da8958/168c66b32421d8e8d5bc13a0bbb87a30.jpeg"
],
"robotType": "08",
"eventFloor": null,
"floorName": null,
"coordId": null,
"coord": null,
"coordName": null,
"positonName": "A3",
"processingRemark": null,
"carId": null,
"parkingSpaceType": null,
"parkingSpaceNumber": null,
"carNumber": null,
"eno": null,
"instrument": null,
"evideo": null
},
"rows": null
}
```
# 后台系统功能:
1. WebSocket服务
- 实现WebSocket服务器
- 处理WebSocket连接管理
- 实现消息的接收和响应
- 支持心跳检测和重连机制
2. 认证管理
- 通过第三方的获取token和refresh接口获取token和refreshToken
- 实现token自动刷新机制
- token失效自动重试机制
3. 数据采集
- 定时调用列表页接口获取事件数据
- 实现增量采集,避免重复处理
- 异常重试机制
- 并发控制
4. 数据处理
- 图片下载和预处理
- OCR识别温度数据
- 数据清洗和验证
- 异常数据处理
5. 数据存储
- 事件信息表
- 图片信息表
- 温度数据表
- 处理日志表
6. API接口
- WebSocket接口
- 温度数据查询接口
- 处理状态查询接口
- 事件管理接口(增删改查)
- 手动触发处理接口
- 系统状态监控接口
- 条件获取列表接口
- 查看列表项详情接口,支持分页查询
- 修改列表详情接口
- 删除列表某一项接口
# 数据库设计:
1. 事件表(event)
- event_id varchar(50) primary key 事件Id
- tenant_info_id varchar(100)
- tenant_info_id varchar(100)
- report_event_id varchar(100)
- number varchar(20)
- name varchar(20)
@ -301,8 +310,8 @@
- evideo varchar(40)
- create_time datetime COMMENT '本地后台创建时间'
- update_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '本地后台更新时间'
2. 图片表(image)
- image_id: VARCHAR(40) PRIMARY KEY COMMENT '图片ID'
- event_id: VARCHAR(50) NOT NULL COMMENT '关联事件ID'
- image_url: VARCHAR(500) NOT NULL COMMENT '图片URL'
@ -310,8 +319,8 @@
- create_time: DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
- INDEX idx_event_id (event_id),
- FOREIGN KEY (event_id) REFERENCES event(event_id)
3. 温度数据表(temperature)
- temp_id: VARCHAR(32) PRIMARY KEY COMMENT '温度记录ID'
- event_id: VARCHAR(50) NOT NULL COMMENT '关联事件ID'
- image_id: VARCHAR(40) NOT NULL COMMENT '关联图片ID'
@ -322,8 +331,8 @@
- INDEX idx_create_time (create_time),
- FOREIGN KEY (event_id) REFERENCES event(event_id),
- FOREIGN KEY (image_id) REFERENCES image(image_id)
4. 处理日志表(process_log)
- log_id: VARCHAR(32) PRIMARY KEY COMMENT '日志ID'
- event_id: VARCHAR(32) NOT NULL COMMENT '关联事件ID'
- process_status: TINYINT NOT NULL COMMENT '处理状态'
@ -334,22 +343,21 @@
- FOREIGN KEY (event_id) REFERENCES event(event_id)
# 性能要求:
- 系统响应时间API接口响应时间<500ms
- 并发处理能力支持10个并发请求
- 数据处理能力每分钟处理不少于100张图片
- 系统可用性99.9%
# 安全要求:
- 实现接口认证机制
- 敏感数据加密存储
- 操作日志记录
- 异常监控告警
# 部署要求:
- 支持Docker容器化部署
- 支持多环境配置(开发、测试、生产)
- 提供部署文档和运维手册

27
doc/接口.md Normal file
View File

@ -0,0 +1,27 @@
## 获取事件列表
- GET /api/v1/events?start_time=2024-01-01T00:00:00&end_time=2024-12-31T23:59:59&etype=日常巡检&area=区域1&skip=0&limit=100
## 获取事件详情
- GET /api/v1/events/{event_id}
## 更新事件
- PUT /api/v1/events/{event_id}
Content-Type: application/json
- ```json
{
"name": "新名称",
"area": "新区域",
"processingRemark": "新备注"
}
```
## 删除事件
- DELETE /api/v1/events/{event_id}
# 运行程序
- python run.py

View File

@ -0,0 +1,52 @@
Global:
model_name: PP-OCRv4_server_det
Hpi:
backend_configs:
paddle_infer:
trt_dynamic_shapes: &id001
x:
- - 1
- 3
- 32
- 32
- - 1
- 3
- 736
- 736
- - 1
- 3
- 4000
- 4000
tensorrt:
dynamic_shapes: *id001
PreProcess:
transform_ops:
- DecodeImage:
channel_first: false
img_mode: BGR
- DetLabelEncode: null
- DetResizeForTest: null
- NormalizeImage:
mean:
- 0.485
- 0.456
- 0.406
order: hwc
scale: 1./255.
std:
- 0.229
- 0.224
- 0.225
- ToCHWImage: null
- KeepKeys:
keep_keys:
- image
- shape
- polys
- ignore_tags
PostProcess:
name: DBPostProcess
thresh: 0.3
box_thresh: 0.6
max_candidates: 1000
unclip_ratio: 1.5

File diff suppressed because it is too large Load Diff

11
run.py Normal file
View File

@ -0,0 +1,11 @@
import uvicorn
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="10.0.0.202",
port=9123,
# reload=True, # 开发模式下启用热重载
workers=1, # 生产环境可以增加worker数量
log_level="info"
)