部署paddleocr

最近接了 一个需求,客户想上传pdf,系统识别pdf内容并保存,用于后续内容检索。其实在我看来不如招一个打字员,服务器接收到文件直接让打字员识别,这样准确率又高,至于效率嘛那得看给别人开多少的工资了。
奈何我不是老板,所以只能苦哈哈的去找能够代替打字员工作的方案了。
目前市面上常用的tess4j、百度OCR、Tesseract-OCR、百度paddle。前三个要么收费,要么就是准确率要低一些。用现在的话来说,不是买不起,而是paddle更具性价比。
PaddleOCR主流的两种部署方式,一种是基于cpu部署,但是识别速度大概有此处省略1万字那么长,另外一种是基于gpu部署,将gpu参与计算,速度还是很客观的。这里主要讲的也是gpu部署。

Serving 服务化部署(Python/C++)

基于GPU PaddleHub Serving的部署

1.环境准备 Ubuntu、python3、显卡、 CUDA、CUDNN、conda3

1.1安装Nvidia基本驱动
查看可以安装的显卡驱动型号,后缀recommend是系统推荐安装的版本
ubuntu-drivers device

自动安装显卡驱动
ubuntu-drivers autoinstall  /  (apt install nvidia-driver-xxx 选择具体版本)

安装成功后输入reboot 重启机器命令nvidia-smi 即可验证是否安装成功,同时可以看到cuda最高支持的版本

1.2安装cuda
apt-get update
官网下载相关的安装包 https://developer.nvidia.com/cuda-11-7-0-download-archive
我这里选择的本地安装下载runfile包上传服务器并执行文件(具体版本根据显卡以及paddle官网支持的版本,目前最高支持11.7)
wget https://developer.download.nvidia.com/compute/cuda/11.7.0/local_installers/cuda_11.7.0_515.43.04_linux.run
sh cuda_11.7.0_515.43.04_linux.run

设置环境变量
sudo nano ~/.bashrc
打开文件写入环境变量
# 文本最后添加以下内容:
export CUDA_HOME=/usr/local/cuda
export PATH=${CUDA_HOME}/bin:${PATH}
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:$LD_LIBRARY_PATH
使生效
source ~/.bashrc
检测是否成功
nvcc -V

1.3安装cudnn
官网下载相关tar包 https://developer.nvidia.com/rdp/cudnn-download
解压文件,对应版本要进行替换
tar -xvf cudnn-linux-x86_64-8.x.x.x_cudaX.Y-archive.tar.xz
将加压后的文件拷贝到cuda并修改权限
sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda/include 
sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda/lib64 
sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*
这里的路径要注意匹配上面的环境变量的路径

1.4安装python3
apt-get install zlib1g-dev libbz2-dev libssl-dev libncurses5-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libpcap-dev xz-utils libexpat1-dev liblzma-dev libffi-dev libc6-dev

下载python压缩包:
wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz
解压缩:
tar -vxzf Python-3.8.10.tgz

cd Python-3.8.10
编译安装:
./configure --prefix=/usr/local/python3 --with-ssl  #此处指定python安装目录
make
make install

建立软连接(相当于快捷方式),建立完后可以直接使用python3命令:
sudo ln -s /usr/local/python3/bin/python3 /usr/bin/python3
sudo ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3

没有软连接的话pip3和python3均要使用绝对路径, 如 /usr/local/python3/bin/python3

使用pip3安装模块时,若因网络原因安装失败 可尝试指定安装源 -i https://pypi.tuna.tsinghua.edu.cn/simple

1.5安装anconda
下载:
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2021.11-Linux-x86_64.sh --no-check-certificate
注意conda相对应的系统内核版本,根据实际情况在https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive查找相应版本

sh Anaconda3-2021.11-Linux-x86_64.sh
之后一直输入yes
若最后一步直接回车,则默认输入了no
需要手动执行:
eval "$(/home/admin/anaconda3/bin/conda shell.bash hook)"
conda init

2.安装 Hub Serving

安装paddlehub模块
conda install paddlepaddle-gpu==2.5.2 cudatoolkit=11.7 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/ -c conda-forge
下载分类、检测、识别推理模型并解压
https://github.com/PaddlePaddle/PaddleOCR/blob/static/doc/doc_ch/quickstart.md

mkdir PaddleOCR
cd PaddleOCR
mkdir inference
cd inference

将下载的推理模型上传至服务器 inference文件下
在这里插入图片描述

下载PaddleOCR
https://codeload.github.com/PaddlePaddle/PaddleOCR/zip/refs/heads/release/2.7

上传至服务器并解压
unzip PaddleOCR-release-2.7.zip

移动至PaddleOCR-develop
mv PaddleOCR-release-2.7 PaddleOCR-develop

cd PaddleOCR-develop
# 安装检测服务模块,如果缺模块直接pip3 install 相关模块即可:  
hub install deploy/hubserving/ocr_det/

# 或,安装识别服务模块:  
hub install deploy/hubserving/ocr_rec/

# 或,安装检测+识别串联服务模块:  
hub install deploy/hubserving/ocr_system/

修改config.json文件
vi deploy/hubserving/ocr_system/config.json

在这里插入图片描述

修改deploy/hubserving/ocr_system文件夹下params.py文件
修改det_model_dir、rec_model_dir、rec_char_dict_path、cls_model_dir路径
在PaddleOCR文件夹下
为保证运行 修改成绝对路径

在这里插入图片描述

3.启动服务

这里采用的是指定路径启动,需要切换到PaddleOCR-develop目录下通过命令
hub serving start -c deploy/hubserving/ocr_system/config.json


建议后台启动,采用screen新建窗口
screen -S OCR
export CUDA_VISIBLE_DEVICES=0
 /usr/local/python3/bin/hub serving start -c deploy/hubserving/ocr_system/config.json

crtl+a+d 窗口离线

4.java接口调试

不能直接识别pdf,这里采用pdf转图片并识别

package com.dqzh.construction.utils;


import com.dqzh.construction.custom.ResultData;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 2 * @Author: zxc
 * 3 * @Date: 2023-10-16 1:21
 * 4
 */
@RestController
@RequestMapping("/test")
public class OCRController {


    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/uploadV2")
    public ResultData upload(@RequestParam(value = "file", required = false) MultipartFile file) throws IOException {
        try {
            //创建请求头
            HttpHeaders headers = new HttpHeaders();
            //设置请求头格式
            headers.setContentType(MediaType.APPLICATION_JSON);
            //构建请求参数
            MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
            //读入静态资源文件
            StringBuilder builder = new StringBuilder();
            try (PDDocument document = PDDocument.load(file.getInputStream())
            ) {
                PDFRenderer pdfRenderer = new PDFRenderer(document);
                for (int page = 0; page < document.getNumberOfPages(); ++page) {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300);
                    ImageIO.write(bim, "jpg", baos);
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
                    // 使用inputStream进行后续操作
                    map.put("images", Collections.singletonList(ImageToBase64(inputStream)));
                    //构建请求
                    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
                    //发送请求
                    //Send the request
                    //根据服务器地址修改ip
                    Map json = restTemplate.postForEntity("http://127.0.0.1:8868/predict/ocr_system", request, Map.class).getBody();
                    //解析Json返回值
                    //Parse the Json return value
                    List<List<Map>> json1 = (List<List<Map>>) json.get("results");
                    List<Map> maps = json1.get(0);

                    for (Map map1 : maps) {
                        builder.append(map1.get("text"));
                    }
                    // 关闭流
                    inputStream.close();
                }
                return ResultData.success(builder);
            } catch (Exception e) {
                e.printStackTrace();
                return ResultData.success("读取失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return ResultData.success("读取失败");

        }

    }

    public static String ImageToBase64(InputStream imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        //Read the image byte array
        try {
            data = new byte[imgPath.available()];
            imgPath.read(data);
            imgPath.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        //Base64 encoding of byte array
        Base64.Encoder encoder = Base64.getEncoder();
        // 返回Base64编码过的字节数组字符串
        //Returns a Base64 encoded byte array string
//        System.out.println(encoder.encodeToString(data));
        return encoder.encodeToString(data);
    }

}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值