从零到一:在 Windows 上本地部署 PaddleOCR 并封装为 API(无 GPU,无 GitHub)
从零到一在 Windows 上本地部署 PaddleOCR 并封装为 API无 GPU无 GitHub前言你是否需要一个本地运行的 OCR 服务能够识别图片中的文字并返回坐标本文会带你从零开始在 Windows 11 系统无独立显卡上使用 Python 虚拟环境部署 PaddleOCR并封装为 HTTP API 接口。全程使用国内镜像无需访问 GitHub。最终效果通过 Postman 上传一张图片返回识别出的文字、置信度以及每个文字框的四个顶点坐标方便在前端绘制标记框。一、环境准备1.1 确认基础环境操作系统Windows 10/1164位Python3.10.11已安装硬件无 NVIDIA 显卡使用 CPU 推理i7 处理器足够1.2 创建虚拟环境为了避免依赖冲突使用 Python 自带的venv创建独立环境。# 在桌面创建一个项目文件夹cd%userprofile%\Desktopmkdirmy_ocr_projectcdmy_ocr_project# 创建虚拟环境python-mvenv paddle_new# 激活虚拟环境Windowspaddle_new\Scripts\activate激活成功后命令行提示符前会出现(paddle_new)。1.3 升级 pippython-mpipinstall--upgradepip二、安装核心依赖使用国内镜像清华源、百度源加速下载。2.1 安装 PaddlePaddleCPU 版本pipinstallpaddlepaddle2.6.2-ihttps://pypi.tuna.tsinghua.edu.cn/simple2.2 安装 PaddleOCR低于 3.0 版本pipinstallpaddleocr3.0-ihttps://pypi.tuna.tsinghua.edu.cn/simple2.3 安装 Flask 和 OpenCVpipinstallflask-ihttps://pypi.tuna.tsinghua.edu.cn/simple pipinstallopencv-python-headless-ihttps://pypi.tuna.tsinghua.edu.cn/simpleopencv-python-headless不包含 GUI 功能体积更小适合服务器环境。2.4 验证安装python-cfrom paddleocr import PaddleOCR; print(Success)若无报错说明安装成功。三、编写 OCR API 服务我们将编写一个 Flask 应用提供两个接口POST /ocr上传图片返回识别结果含坐标GET /health健康检查3.1 创建app_with_coords.py在my_ocr_project文件夹下新建app_with_coords.py将下面完整代码复制进去。# -*- coding: utf-8 -*- PaddleOCR Web API 服务 - 稳定版 - 识别图片中的文字 - 返回文字、置信度、文本框四点坐标 importosimporttempfileimportcv2importnumpyasnpfromflaskimportFlask,request,jsonifyfrompaddleocrimportPaddleOCR appFlask(__name__)# ---------- 配置区 ----------# 是否启用图像预处理默认关闭若开启则仅做灰度化轻微降噪ENABLE_PREPROCESSos.environ.get(ENABLE_PREPROCESS,false).lower()trueENABLE_MEDIAN_BLURos.environ.get(ENABLE_MEDIAN_BLUR,false).lower()true# -------------------------# 初始化 OCR 模型参数稳定适用于通用场景ocrPaddleOCR(use_angle_clsTrue,# 方向分类处理颠倒文字langch,# 中英文模型det_db_thresh0.3,# 检测阈值det_db_box_thresh0.6,# 检测框过滤阈值det_db_unclip_ratio2.0,# 文本框扩大比例rec_image_shape3,32,320# 识别尺寸)defgentle_preprocess(image_path):温和预处理灰度化 可选轻微中值滤波不改变尺寸不二值化imgcv2.imread(image_path)ifimgisNone:returnNonegraycv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ifENABLE_MEDIAN_BLUR:graycv2.medianBlur(gray,3)returngraydefconvert_to_serializable(obj):将 numpy 类型递归转换为 Python 原生类型以便 JSON 序列化ifisinstance(obj,(np.integer,np.int64,np.int32)):returnint(obj)elifisinstance(obj,(np.floating,np.float64,np.float32)):returnfloat(obj)elifisinstance(obj,np.ndarray):returnobj.tolist()elifisinstance(obj,bytes):returnobj.decode(utf-8)elifisinstance(obj,(tuple,list)):return[convert_to_serializable(i)foriinobj]elifisinstance(obj,dict):return{k:convert_to_serializable(v)fork,vinobj.items()}else:returnobjapp.route(/ocr,methods[POST])defocr_api():上传图片返回 OCR 识别结果# 校验文件iffilenotinrequest.files:returnjsonify({success:False,message:缺少 file 字段}),400filerequest.files[file]iffile.filename:returnjsonify({success:False,message:未选择文件}),400# 校验扩展名allowed{.jpg,.jpeg,.png,.bmp,.tiff}extos.path.splitext(file.filename)[1].lower()ifextnotinallowed:returnjsonify({success:False,message:f不支持的图片格式允许{allowed}}),400tmp_pathNonetry:# 保存临时文件withtempfile.NamedTemporaryFile(deleteFalse,suffixext)astmp:file.save(tmp.name)tmp_pathtmp.name# 可选预处理默认关闭ifENABLE_PREPROCESS:processedgentle_preprocess(tmp_path)ifprocessedisnotNone:cv2.imwrite(tmp_path,processed)# OCR 识别resultocr.ocr(tmp_path,clsTrue)# 解析结果ocr_data[]ifresultandresult[0]:forlineinresult[0]:box_pointsline[0]# 四点坐标text,confidenceline[1]# 文字和置信度ocr_data.append({text:text,confidence:round(float(confidence),4),box_points:convert_to_serializable(box_points)})# 清理临时文件os.unlink(tmp_path)returnjsonify({success:True,message:f识别成功共{len(ocr_data)}条文字,data:ocr_data}),200exceptExceptionase:iftmp_pathandos.path.exists(tmp_path):os.unlink(tmp_path)returnjsonify({success:False,message:fOCR 处理失败:{str(e)}}),500app.route(/health,methods[GET])defhealth_check():returnjsonify({status:ok,message:PaddleOCR API 服务运行中}),200if__name____main__:# 启动服务监听所有网卡端口 5000app.run(host0.0.0.0,port5000,debugFalse)3.2 启动服务python app_with_coords.py看到如下输出表示启动成功* Running on http://0.0.0.0:5000 * Running on http://127.0.0.1:5000注意如果端口 5000 被占用可以修改代码中的port5000为其他端口如8080。四、调用 API4.1 使用 Postman 调用新建请求MethodPOSTURLhttp://127.0.0.1:5000/ocr设置 Body选择form-dataKEY 填写file类型选择File不是 TextVALUE 选择你要识别的图片文件发送请求返回示例{success:true,message:识别成功共 13 条文字,data:[{text:XXXXXX科技有限公司,confidence:0.9976,box_points:[[79,16],[491,24],[490,53],[78,46]]},{text:型号,confidence:0.9998,box_points:[[44,55],[75,55],[75,81],[44,81]]}// ... 更多结果]}4.2 使用 curl 调用curl-XPOST http://127.0.0.1:5000/ocr-FfileC:/path/to/your/image.jpg五、坐标的用途前端绘制标记框返回的box_points是一个包含四个点的数组按顺时针方向左上、右上、右下、左下排列。你可以用这些坐标在 HTML5 Canvas 上绘制矩形框。以下是一个简单的前端示例imgidsource-imgsrcyour-image.jpgstyledisplay:none;canvasidocr-canvas/canvasscriptconstocrResult{data:[{text:XXXX科技有限公司,box_points:[[79,16],[491,24],[490,53],[78,46]]}]};constimgdocument.getElementById(source-img);constcanvasdocument.getElementById(ocr-canvas);constctxcanvas.getContext(2d);img.onload(){canvas.widthimg.width;canvas.heightimg.height;ctx.drawImage(img,0,0);ctx.strokeStylered;ctx.lineWidth2;ocrResult.data.forEach(item{constpointsitem.box_points;ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(leti1;ipoints.length;i)ctx.lineTo(points[i][0],points[i][1]);ctx.closePath();ctx.stroke();ctx.fillStylered;ctx.font16px Arial;ctx.fillText(item.text,points[0][0],points[0][1]-5);});};img.srcyour-image.jpg;/script六、常见问题与优化6.1 模型下载慢或失败首次运行时PaddleOCR 会自动下载模型文件。如果速度慢可以在代码开头添加环境变量强制使用百度云源importos os.environ[PADDLE_PDX_MODEL_SOURCE]BOS6.2 识别结果不理想调整检测阈值修改det_db_thresh0.2~0.4和det_db_box_thresh0.5~0.7。启用轻微预处理启动服务前设置环境变量开启灰度中值滤波setENABLE_PREPROCESStruesetENABLE_MEDIAN_BLURtrue python app_with_coords.py升级模型新版本 PaddleOCR 支持 PP-OCRv5但需要安装paddlepaddle3.0.0。如需尝鲜可创建新环境尝试。6.3np未定义错误我们的代码中已包含import numpy as np并使用convert_to_serializable函数解决了 numpy 类型序列化问题。6.4 端口被占用修改app.run(port5000)为其他端口如8080。七、总结通过本文你完成了以下工作在没有 GPU 和访问 GitHub 限制的情况下成功本地部署 PaddleOCR。使用 Python 虚拟环境隔离依赖安装指定版本的 PaddlePaddle 和 PaddleOCR。编写 Flask API 服务返回文字、置信度和精确的文本框坐标。学会了使用 Postman 调用接口并了解了如何在前端绘制识别框。这套 OCR 服务可以轻松集成到任何需要文字识别的应用中例如自动化办公、图片内容提取、票据识别等。下一步建议将 API 部署到服务器使用waitress或gunicorn作为生产 WSGI 服务器。收集特定场景的图片对模型进行微调Fine-tuning以获得更高精度。结合 RabbitMQ 或 Celery 实现异步 OCR 任务队列。祝你部署顺利如有问题欢迎交流本教程基于实际成功经验编写所有命令和代码均已测试通过。使用的版本组合Python 3.10.11, paddlepaddle 2.6.2, paddleocr3.0, flask, opencv-python-headless。