基于docker+python+paddleocr构建自己本地化ocr服务

news2025/3/13 11:48:13

1、使用FastAPI创建服务实例

1.1、正常程序

from fastapi import FastAPI, UploadFile, File, HTTPException
from typing import List
from paddleocr import PaddleOCR
import numpy as np
from PIL import Image
import io
import logging

app = FastAPI(title="游戏截图OCR识别接口")
ocr = PaddleOCR(lang='ch', use_angle_cls=True)  # 启用方向分类器
logger = logging.getLogger("uvicorn.error")

@app.post("/ocrImages")
async def process_game_screenshots(
    images: List[UploadFile] = File(...,description="上传游戏截图(支持PNG/JPG格式)")
):
    """
    游戏截图文本识别接口
    - 支持同时上传最多10张截图
    - 单文件大小限制:5MB
    - 响应时间:约2秒/张(取决于文本复杂度)
    """
    results = []
    
    for screenshot in images:
        try:
            # 验证文件类型
            if screenshot.content_type not in ["image/jpeg", "image/png"]:
                raise HTTPException(400, detail=f"不支持的文件格式: {screenshot.filename}")

            # 读取并验证文件大小
            contents = await screenshot.read()
            if len(contents) > 5 * 1024 * 1024:
                raise HTTPException(413, detail=f"文件过大: {screenshot.filename}")

            # 转换图像格式
            img = Image.open(io.BytesIO(contents)).convert('RGB')
            img_array = np.array(img)

            # 执行OCR识别
            ocr_result = ocr.ocr(img_array, cls=True)
            
            # 提取文本内容(过滤低置信度结果)
            texts = []
            if ocr_result:
                for page in ocr_result:
                    if page:  # 忽略空页
                        texts.extend(line[1][0] for line in page if line[1][1] > 0.6)

            results.append({
                "filename": screenshot.filename,
                "texts": texts
            })

        except HTTPException as he:
            logger.warning(f"验证失败: {he.detail}")
            results.append({
                "filename": screenshot.filename,
                "error": he.detail
            })
        except Exception as e:
            logger.error(f"处理失败: {screenshot.filename} - {str(e)}")
            results.append({
                "filename": screenshot.filename,
                "error": "内部处理错误"
            })
    
    return {"results": results}

# 运行服务(生产环境建议使用uvicorn命令行启动)
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8888)

1.2、考虑并发

from fastapi import FastAPI, UploadFile, File, HTTPException
from typing import List
from paddleocr import PaddleOCR
import numpy as np
from PIL import Image
import io
import logging
import asyncio

app = FastAPI(title="游戏截图OCR识别接口")
logger = logging.getLogger("uvicorn.error")

# 调整OCR配置,根据实际情况启用GPU或MKLDNN
ocr = PaddleOCR(
    lang='ch',
    use_angle_cls=True,
    use_gpu=False,  # 根据环境调整,若无GPU则设为False
    det_limit_side_len=1600,
    det_db_thresh=0.4,
    det_db_box_thresh=0.6,
    rec_batch_num=5,
    enable_mkldnn=True  # 若CPU不支持MKLDNN则禁用
)

async def async_ocr(img_array: np.ndarray):
    """异步OCR处理,添加线程锁确保安全"""
    loop = asyncio.get_event_loop()
    # 使用线程锁(需导入threading)
    from threading import Lock
    lock = Lock()
    with lock:  # 确保同一时间仅一个线程调用OCR
        return await loop.run_in_executor(
            None, 
            lambda: ocr.ocr(img_array, cls=True)
        )

def preprocess_image(img: Image.Image) -> np.ndarray:
    # 保持不变
    w, h = img.size
    if max(w, h) > 1600:
        scale = 1600 / max(w, h)
        img = img.resize((int(w*scale), int(h*scale)), Image.Resampling.LANCZOS)
    return np.array(img)

@app.post("/ocrImages")
async def process_game_screenshots(
    images: List[UploadFile] = File(...,description="上传游戏截图(支持PNG/JPG格式)")
):
    results = []
    tasks = []
    for screenshot in images:
        if screenshot.content_type not in ["image/jpeg", "image/png"]:
            results.append({"filename": screenshot.filename, "error": "不支持的格式"})
            continue
        tasks.append(process_single_image(screenshot))
    
    # 限制最大并发数,例如设置为2
    from concurrent.futures import ThreadPoolExecutor
    executor = ThreadPoolExecutor(max_workers=2)
    results = await asyncio.gather(*tasks, return_exceptions=True)
    # 处理异常
    processed_results = []
    for res in results:
        if isinstance(res, Exception):
            logger.error(f"处理异常: {str(res)}")
            processed_results.append({"error": "内部错误"})
        else:
            processed_results.append(res)
    return {"results": processed_results}

async def process_single_image(screenshot: UploadFile):
    try:
        contents = await screenshot.read()
        if len(contents) > 5 * 1024 * 1024:
            raise HTTPException(413, detail="文件过大")
        
        img = Image.open(io.BytesIO(contents)).convert('RGB')
        img_array = preprocess_image(img)
        
        ocr_result = await async_ocr(img_array)
        
        texts = []
        for page in ocr_result:
            if page:
                texts.extend(
                    line[1][0] 
                    for line in page 
                    if line[1][1] > 0.65
                )
        
        return {
            "filename": screenshot.filename,
            "texts": texts,
            "warning": "检测到低精度内容" if len(texts)<3 else None
        }
    
    except Exception as e:
        logger.error(f"处理失败: {screenshot.filename} - {str(e)}")
        return {"filename": screenshot.filename, "error": "处理失败"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8888)

2、使用Docker打包镜像

2.1、编写Dockerfile

# 使用 Python 基础镜像
# 第一阶段:构建环境
FROM python:3.9-slim as builder

# 创建APT源文件
RUN echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib" > /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/debian-security bullseye-security main" >> /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/debian/ bullseye-updates main" >> /etc/apt/sources.list

# 安装基础工具
RUN apt-get update && apt-get install -y \
    ca-certificates \
    gnupg2 \
    && apt-get clean

# 安装编译依赖
RUN apt-get update && apt-get install -y \
    gcc \
    python3-dev \
    libgl1-mesa-glx \
    libglib2.0-0 \
    libgomp1 \
    libsm6 \
    libxext6 \
    libxrender-dev \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .

# 使用国内PyPI镜像
RUN pip install --user --no-cache-dir -r requirements.txt \
    -i https://pypi.tuna.tsinghua.edu.cn/simple \
    --trusted-host pypi.tuna.tsinghua.edu.cn

# 第二阶段:生产镜像
FROM python:3.9-slim

# 初始化生产环境源文件
RUN echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib" > /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/debian-security bullseye-security main" >> /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/debian/ bullseye-updates main" >> /etc/apt/sources.list

# 安装运行时依赖
RUN apt-get update && apt-get install -y \
    libgl1-mesa-glx \
    libglib2.0-0 \
    libgomp1 \
    && rm -rf /var/lib/apt/lists/*

# 复制构建结果
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 复制应用代码
COPY . .

EXPOSE 6012

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "6012"]

2.2 requirements.txt

fastapi
uvicorn
python-multipart
paddlepaddle
paddleocr
opencv-python-headless

2.3 构建镜像&运行容器

# 构建镜像(使用国内缓存)
docker build -t ocr-server:v1 .

启动

docker run -d -p 6012:6012 \
  --name ocr-service \
  --restart always \
  ocr-server:v1

目录结构
your_project/
├── app.py # FastAPI 主程序
├── Dockerfile # Docker 构建文件
└── requirements.txt # 依赖列表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2314278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

51单片机Proteus仿真速成教程——P1-软件与配置+Proteus绘制51单片机最小系统+新建程序模版

前言&#xff1a;本文主要围绕 51 单片机最小系统的绘制及程序模板创建展开。首先介绍了使用 Proteus 绘制 51 单片机最小系统的详细步骤&#xff0c;包括软件安装获取途径、工程创建、器件添加&#xff08;如单片机 AT89C51、晶振、电容、电阻、按键等&#xff09;、外围电路&…

使用 pytesseract 进行 OCR 识别:以固定区域经纬度提取为例

引言 在智能交通、地图定位等应用场景中&#xff0c;经常会遇到需要从图像中提取经纬度信息的需求。本篇文章将介绍如何利用 Python 的 pytesseract 库结合 PIL 对图像进行预处理&#xff0c;通过固定区域裁剪&#xff0c;来有效地识别出图像上显示的经纬度信息。 1. OCR 与 …

【51单片机】程序实验15.DS18B20温度传感器

主要参考学习资料&#xff1a;B站【普中官方】51单片机手把手教学视频 开发资料下载链接&#xff1a;http://www.prechin.cn/gongsixinwen/208.html 单片机套装&#xff1a;普中STC51单片机开发板A4标准版套餐7 目录 DS18B20介绍主要特性内部结构控制时序初始化时序写时序读时序…

Vue项目上传到GitHub,vscode拉取vue项目更新后推送到GitHub上

1、新建Vue项目 2、在GitHub新建仓库 3、留意建立好仓库后提示的命令 4、进入vue项目目录&#xff0c;在空白处点击鼠标右键选择git bash here 5、输入命令 git init git add . git commit -m "注释内容" 输入之前创建GitHub仓库后记下的代码的第一句 git remote…

InternVL:论文阅读 -- 多模态大模型(视觉语言模型)

更多内容&#xff1a;XiaoJ的知识星球 文章目录 InternVL: 扩展视觉基础模型与通用视觉语言任务对齐1.概述2.InternVL整体架构1&#xff09;大型视觉编码器&#xff1a;InternViT-6B2&#xff09;语言中间件&#xff1a;QLLaMA。3&#xff09;训练策略&#xff08;1&#xff09…

【BUG】类文件具有错误的版本 61.0, 应为 52.0,请删除该文件或确保该文件位于正确的类路径子目录中。

报错&#xff1a; [ERROR] 类文件具有错误的版本 61.0, 应为 52.0 [ERROR] 请删除该文件或确保该文件位于正确的类路径子目录中。 报错截图&#xff1a; 原因&#xff1a;Java 版本和 Spring 不兼容&#xff0c;显示 Spring 版本过高 解决方法 1. 使用更高版本的 J…

康谋应用 | 基于多传感器融合的海洋数据采集系统

在海洋监测领域&#xff0c;基于无人艇能够实现高效、实时、自动化的海洋数据采集&#xff0c;从而为海洋环境保护、资源开发等提供有力支持。其中&#xff0c;无人艇的控制算法训练往往需要大量高质量的数据支持。然而&#xff0c;海洋数据采集也面临数据噪声和误差、数据融合…

双周报Vol.67: 模式匹配支持守卫、LLVM 后端发布、支持 Attribute 语法...多项核心技术更新!

2025-03-10 语言更新 模式匹配支持守卫&#xff08;Pattern Guard&#xff09; 模式守卫可以通过在模式后追加 if ... 的语法结构来指定。有模式守卫的分支只有在被模式匹配的值满足对应模式&#xff0c;并且模式守卫为真的情况下才会执行。如果模式守卫为假&#xff0c;则会…

MCP-代码解读TypeScript版本

MCP-代码解读TypeScript版本 文章目录 MCP-代码解读TypeScript版本1-参考网址2-TypeScript代码3-代码解读1-[非重点]定义函数2-[非重点]定义工具说明3-[重点]运行MCP服务 1-参考网址 B站视频参考 2-TypeScript代码 import { McpServer } from "modelcontextprotocol/sd…

写了一个二叉树构造函数和画图函数,方便debug

代码 class TreeNode(object):def __init__(self, val, leftNone, rightNone):self.val valself.left leftself.right rightdef construct_tree(nodes):if not nodes:return Noneroot TreeNode(nodes[0])queue [root]index 1while index < len(nodes):node queue.p…

docker 小记

一、卸载 查看当前版本 docker -v2. 如果有&#xff0c;先停止docker systemctl stop docker如果是yum安装&#xff0c;卸载方式为 #已防版本冲突&#xff0c;直接卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-lat…

G-Star 公益行起航,挥动开源技术点亮公益!

公益组织&#xff0c;一直是社会温暖的传递者&#xff0c;但在数字化浪潮中&#xff0c;也面临着诸多比大众想象中复杂的挑战&#xff1a;项目管理如何更高效&#xff1f;志愿者管理又该如何创新&#xff1f;宣传推广怎么才能更有影响力&#xff1f;内部管理和技术支持又该如何…

k9s入门及实战

概述 k9s&#xff0c;GitHub&#xff0c;是用于管理k8s集群的CLI&#xff0c;提供一个终端UI来与k8s集群进行交互。通过封装kubectl功能&#xff0c;k9s会以特定时间间隔监控k8s的变化&#xff0c;默认为2秒&#xff0c;并提供后续命令来与k8s资源进行交互&#xff0c;k9s可让…

redis增加ip白名单

Redis增加IP白名单 随着互联网的快速发展&#xff0c;网络安全问题也日益凸显。为了保护服务器安全&#xff0c;我们常常需要对访问服务器的IP地址进行限制。而Redis作为一种高性能的缓存数据库&#xff0c;可以用来实现IP白名单功能。本文将介绍如何使用Redis来增加IP白名单&…

git commit messege 模板设置 (规范化管理git)

配置方法 git config --global core.editor vim &#xff08;设置 Git 的默认编辑器为 Vim&#xff09;在用户根目录下&#xff08;~&#xff09;&#xff0c;创建一个.git_commit_msg文件&#xff0c;然后把下面的内容拷贝到文件中并保存。 [version][模块][类型]{解决xxx问题…

Franka机器人ROS 2 发布:赋能机器人研究和行业应用

Franka机器人 ROS 2 发布&#xff1a;赋能机器人研究和行业应用 Franka ROS 2 发布&#xff1a;赋能机器人研究和行业应用 由zlem Odeh 于Franka Robotics 发布 在机器人操作系统 (ROS) 等技术和生态系统的推动下&#xff0c;机器人世界正以前所未有的速度发展。ROS 2 是广受…

docker部署jenkins,安装使用一条龙教程

Jenkins k8s 实现CI/CD 一、简介 1. JenKins是什么? Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。 2. 什么是CI / CD…

短视频下载去水印,用什么工具好?

去除视频和图片水印是许多用户的需求&#xff0c;尤其是在分享或保存内容时。以下是6款超好用的工具&#xff0c;帮助你轻松去除水印&#xff0c;享受纯净的视觉体验&#xff1a; 1. 易下载去水印小程序 特点&#xff1a; 操作简单&#xff0c;支持抖音、快手、小红书、哔哩哔哩…

推理大模型时代,TextIn ParseX助力出版业知识资产重构

在大语言模型&#xff08;LLM&#xff09;与推理能力快速进化的技术浪潮下&#xff0c;出版机构沉淀数十年的非结构化数据资产&#xff0c;包括书籍、期刊、手稿及历史档案&#xff0c;正在焕发新的机遇。基于文档解析、NLP与大模型的推理生成能力&#xff0c;我们在图书馆层层…

Redis 2025/3/9

Redis主从集群 搭建主从集群 Redis并发能力非常强&#xff0c;单节点能够达到数万的并发。 不过对一些用户规模大&#xff0c;并发量比较高的应用来讲&#xff0c;数万并发不太够。这时候就用到redis的集群了。因为Redis中的数据通常读多写少&#xff0c;所以最常用的集群方…