赞
踩
最近接了 一个需求,客户想上传pdf,系统识别pdf内容并保存,用于后续内容检索。其实在我看来不如招一个打字员,服务器接收到文件直接让打字员识别,这样准确率又高,至于效率嘛那得看给别人开多少的工资了。
奈何我不是老板,所以只能苦哈哈的去找能够代替打字员工作的方案了。
目前市面上常用的tess4j、百度OCR、Tesseract-OCR、百度paddle。前三个要么收费,要么就是准确率要低一些。用现在的话来说,不是买不起,而是paddle更具性价比。
PaddleOCR主流的两种部署方式,一种是基于cpu部署,但是识别速度大概有此处省略1万字那么长,另外一种是基于gpu部署,将gpu参与计算,速度还是很客观的。这里主要讲的也是gpu部署。
基于GPU PaddleHub Serving的部署
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
安装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文件夹下
为保证运行 修改成绝对路径
这里采用的是指定路径启动,需要切换到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 窗口离线
不能直接识别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); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。