1、使用FastAPI创建服务实例
1.1、程序
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import JSONResponse
from paddleocr import PaddleOCR
import uvicorn
from typing import List
from PIL import Image
import numpy as np
import io
import logging
import os
# 根据选择的方案修改以下导入
# 方案一使用:
from pydantic_settings import BaseSettings
from pydantic import ConfigDict
# 方案二使用:
# from pydantic import BaseSettings
class Settings(BaseSettings):
ocr_newline: bool = False
model_dir: str = "./models"
image_resize: tuple = (1280, 720)
# 方案一配置
model_config = ConfigDict(
env_file=".env",
env_prefix="OCR_"
)
# 方案二配置(保持原样)
# class Config:
# env_file = ".env"
# env_prefix = "OCR_"
settings = Settings()
class OCRProcessor:
def __init__(self):
self.ocr = PaddleOCR(
lang='ch',
use_gpu=False, # 关闭 GPU 加速
det_model_dir=os.path.join(settings.model_dir, "ch_PP-OCRv4_det_infer"),
rec_model_dir=os.path.join(settings.model_dir, "ch_PP-OCRv4_rec_infer"),
use_angle_cls=False,
show_log=False
)
async def process_image(self, image_data: bytes) -> str:
try:
image = Image.open(io.BytesIO(image_data))
if image.mode != 'RGB':
image = image.convert('RGB')
image = image.resize(settings.image_resize, Image.LANCZOS)
return self._format_result(self.ocr.ocr(np.array(image), cls=True))
except Exception as e:
logging.error(f"Image processing error: {str(e)}")
raise
def _format_result(self, result: list) -> str:
return ("\n" if settings.ocr_newline else " ").join(
word_info[1][0] for line in result for word_info in line
)
app = FastAPI()
ocr_processor = OCRProcessor()
@app.post("/ocrImages")
async def perform_ocr(images: List[UploadFile] = File(...)):
try:
# 初始化结果容器
all_texts = []
# 遍历处理每张图片
for file in images:
if not file.content_type.startswith('image/'):
raise HTTPException(400, f"文件 {file.filename} 不是图片类型")
# 内存处理图像
image_data = await file.read()
text = await ocr_processor.process_image(image_data)
# 添加带换行的结果
all_texts.append(f"{text}") # 文件名作为注释
# 全量文本用双换行分隔
full_text = "\n".join(all_texts)
return {"ocr_text": full_text}
except HTTPException:
raise
except Exception as e:
raise HTTPException(500, f"处理失败: {str(e)}")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=6012)
# 2、使用Docker打包镜像
## 2.1、编写Dockerfile
```powershell
# 使用 Python 基础镜像
# 使用官方Python基础镜像
FROM python:3.9-slim
# 安装系统依赖(PaddleOCR需要)
RUN apt-get update && apt-get install -y \
libgl1 \
libglib2.0-0 \
libgomp1 \
libstdc++6 \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /app
# 复制项目文件
COPY ./app /app
COPY ./models /app/models
COPY requirements.txt .
# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt
# 暴露端口
EXPOSE 6012
# 启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "6012"]
2.2 requirements.txt
fastapi>=0.68.0
uvicorn>=0.15.0
python-multipart
paddleocr>=2.7.0
paddlepaddle>=2.5.0
numpy
pillow
pydantic-settings
2.3 构建镜像&运行容器
# 构建镜像(使用国内缓存)
docker build --no-cache -t ocr-api .
启动
docker run -d --name ocr_service -p 6012:6012 ocr-api
目录结构
your_project/
├── app/
│ ├── main.py # 你的代码文件
│ └── … # 其他代码文件
├── models/ # 手动下载的PaddleOCR模型
│ ├── ch_PP-OCRv4_det_infer/
│ └── ch_PP-OCRv4_rec_infer/
├── requirements.txt # 依赖清单
└── Dockerfile