PaddlePaddle RapidOcr 使用一则

[[PaddlePaddle_Serving]]

github 项目

PaddleOCR 快速开始

https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7/doc/doc_ch/quickstart.md#11

安装 PaddlePaddle

如果您没有基础的Python运行环境,请参考运行环境准备

  • 您的机器安装的是CUDA9或CUDA10,请运行以下命令安装

    python3 -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple
    
  • 您的机器是CPU,请运行以下命令安装

    # python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple # 不行
    # 用 pip
    pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
    

安装PaddleOCR whl包

pip install "paddleocr>=2.0.1"  -i https://mirror.baidu.com/pypi/simple # 推荐使用2.0.1+版本

paddleocr默认使用PP-OCRv4模型(--ocr_version PP-OCRv4),如需使用其他版本可通过设置参数--ocr_version,具体版本说明如下:

版本名称 版本说明
PP-OCRv4 支持中、英文检测和识别,方向分类器,支持多语种识别
PP-OCRv3 支持中、英文检测和识别,方向分类器,支持多语种识别
PP-OCRv2 支持中英文的检测和识别,方向分类器,多语言暂未更新
PP-OCR 支持中、英文检测和识别,方向分类器,支持多语种识别

Python脚本调用

中英文与多语言使用

通过Python脚本使用PaddleOCR whl包,whl包会自动下载ppocr轻量级模型作为默认模型。

  • 检测+方向分类器+识别全流程
from paddleocr import PaddleOCR, draw_ocr

# Paddleocr目前支持的多语言语种可以通过修改lang参数进行切换
# 例如`ch`, `en`, `fr`, `german`, `korean`, `japan`
ocr = PaddleOCR(use_angle_cls=True, lang="ch")  # need to run only once to download and load model into memory
img_path = './imgs/11.jpg'
result = ocr.ocr(img_path, cls=True)
for idx in range(len(result)):
    res = result[idx]
    for line in res:
        print(line)

# 显示结果
from PIL import Image
result = result[0]
image = Image.open(img_path).convert('RGB')
boxes = [line[0] for line in result]
txts = [line[1][0] for line in result]
scores = [line[1][1] for line in result]
im_show = draw_ocr(image, boxes, txts, scores, font_path='./fonts/simfang.ttf')
im_show = Image.fromarray(im_show)
im_show.save('result.jpg')

结果是一个list,每个item包含了文本框,文字和识别置信度

[[[28.0, 37.0], [302.0, 39.0], [302.0, 72.0], [27.0, 70.0]], ('纯臻营养护发素', 0.9658738374710083)]

RapidOcr (PaddleOCR)

apache 开源文件内容提取 - https://tika.apache.org/
官方仓库PaddleOCR - https://github.com/PaddlePaddle/PaddleOCR
[[PaddlePaddle_OCR]]

RapidOcrNcnnJvm

jni 调用

参考 RapidOcrNcnnJvm - https://github.com/RapidAI/RapidOcrNcnnJvm

  1. 预先编译好的动态运行库复制到run-test文件夹,根据您选择的编译类型,macOS、linux可能还需要额外配置动态库的搜索路径
  2. 从第1步的说明中找到模型下载地址,放到run-test/models文件夹,测试的目标图片放到run-test/images文件夹
  3. 用IDEA打开本项目
  4. Main.java为java版调用范例,main.kt为kotlin版调用范例,之后以kotlin为范例来说明
  5. IDEA中直接在在main方法左边点击绿色的运行图标,可以直接调试运行范例,但此时没有输入参数。
  • 编辑运行参数:顶部工具栏“运行”图标左边,点开下拉菜单“Edit Configurations”
  • VM options:添加-Djava.library.path=run-test,(把run-test文件夹加到java的lib搜索路径)
  • Program arguments 添加命令行输入参数
run-test/models dbnet_op angle_op crnn_lite_op keys.txt run-test/test_imgs/1.jpg

命令行参数models文件夹里必须有相应的模型文件,接下来的四个文件名对应模型文件夹里的3种模型(不含扩展名)和1个keys文件,请确认文件名无误
run-test/images/1.jpg是待识别的目标图片

  • 点击运行,正常的话就可以输出识别结果。

本质上是jni 调用

编译好的动态库 - https://github.com/RapidAi/RapidOcrNcnn/releases 注意是 Ncnn
看项目dll项目 源码.
入口在 https://github.com/RapidAI/RapidOcrOnnx/blob/main/src/main.cpp ;
导出的对象是 https://github.com/RapidAI/RapidOcrOnnx/blob/main/src/OcrLiteJni.cpp ?

um... 实际有哪些函数, 还得看 dll 导出的函数表.. 用IDA静态分析看看

名称	地址	序号
JNI_OnLoad	0000000180010C20	1
JNI_OnUnload	0000000180010C70	2
Java_com_benjaminwan_ocrlibrary_OcrEngine_detect	0000000180010CB0	3
Java_com_benjaminwan_ocrlibrary_OcrEngine_enableResultText	0000000180011410	4
Java_com_benjaminwan_ocrlibrary_OcrEngine_getVersion	0000000180011780	5
Java_com_benjaminwan_ocrlibrary_OcrEngine_initLogger	00000001800117A0	6
Java_com_benjaminwan_ocrlibrary_OcrEngine_initModels	00000001800117D0	7
Java_com_benjaminwan_ocrlibrary_OcrEngine_setGpuIndex	0000000180012730	8
Java_com_benjaminwan_ocrlibrary_OcrEngine_setNumThread	0000000180012740	9
DllEntryPoint	00000001807D7030	[main entry]

package com.benjaminwan.ocrlibrary

class OcrEngine() {
    init {
        try {
	        //对应的是 https://github.com/RapidAI/RapidOcrNcnn/releases/download/1.2.0/windows-jni.7z 下载的 dll库
            System.loadLibrary("RapidOcrNcnn")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    ............
    
    

更多模型可以在官网 https://rapidai.github.io/RapidOCRDocs/model_list/#_1 下载(Onnx格式)

package com.benjaminwan.ocr

import com.benjaminwan.ocrlibrary.OcrEngine

fun main(args: Array<String>) {
	//System.setProperty("java.library.path", "D:\\libarry\\RapidOcrNcnnJvm\\win-JNI-CPU-x64\\bin")
    val jniLibDir = System.getProperty("java.library.path")
    println("java.library.path=$jniLibDir")

	// 对应的是 [Project_RapidOcrNcnn-1.2.0.7z](https://github.com/RapidAI/RapidOcrNcnn/releases/download/1.2.0/Project_RapidOcrNcnn-1.2.0.7z) 下载的模型 及文件
    //------- init models/dir image/path -------
    val modelsDir = "E:\\projects-work\\pdf-classify\\run-test\\models"
    val detName = "ch_PP-OCRv3_det_infer"
    val clsName = "ch_ppocr_mobile_v2.0_cls_infer"
    val recName = "ch_PP-OCRv3_rec_infer"
    val keysName = "ppocr_keys_v1.txt"
    val imagePath = "E:\\projects-work\\pdf-classify\\run-test\\images\\1.jpg"
    println("modelsDir=$modelsDir, detName=$detName, clsName=$clsName, recName=$recName, keysName=$keysName, imagePath=$imagePath")

    //------- numThread -------
    val numThread = if (args.size > 6) args[6].trim().toIntOrNull() ?: 4 else 4

    //------- padding -------
    val padding = if (args.size > 7) args[7].trim().toIntOrNull() ?: 50 else 50

    //------- maxSideLen -------
    val maxSideLen = if (args.size > 8) args[8].trim().toIntOrNull() ?: 1024 else 1024

    //------- boxScoreThresh -------
    val boxScoreThresh = if (args.size > 9) args[9].trim().toFloatOrNull() ?: 0.5f else 0.5f

    //------- boxThresh -------
    val boxThresh = if (args.size > 10) args[10].trim().toFloatOrNull() ?: 0.3f else 0.3f

    //------- unClipRatio -------
    val unClipRatio = if (args.size > 11) args[11].trim().toFloatOrNull() ?: 1.6f else 1.6f

    //------- doAngle -------
    val doAngleFlag = if (args.size > 12) args[12].trim().toIntOrNull() ?: 1 else 1
    val doAngle = (doAngleFlag == 1)

    //------- mostAngle -------
    val mostAngleFlag = if (args.size > 13) args[13].trim().toIntOrNull() ?: 1 else 1
    val mostAngle = (mostAngleFlag == 1)

    //------- gpuIndex -------
    val gpuIndex = if (args.size > 14) args[14].trim().toIntOrNull() ?: 0 else 0
    println("gpuIndex=$gpuIndex")

    //------- get jni version -------
    val ocrEngine = OcrEngine()
    val version = ocrEngine.getVersion()
    println("version=$version")

    //------- setNumThread -------
    ocrEngine.setNumThread(numThread)

    //------- init Logger -------
    ocrEngine.initLogger(
        isConsole = true,//jni启用命令行输出
        isPartImg = true,
        isResultImg = true
    )
    ocrEngine.enableResultText(imagePath)
    ocrEngine.setGpuIndex(gpuIndex)//GPU0一般为默认GPU,参数选项:使用CPU(-1)/使用GPU0(0)/使用GPU1(1)/...
    //------- init Models -------
    val initModelsRet = ocrEngine.initModels(modelsDir, detName, clsName, recName, keysName)
    if (!initModelsRet) {
        println("Error in models initialization, please check the models/keys path!")
        return
    }

    //------- set param -------
    println("padding($padding) boxScoreThresh($boxScoreThresh) boxThresh($boxThresh) unClipRatio($unClipRatio) doAngle($doAngle) mostAngle($mostAngle)")
    ocrEngine.padding = padding //图像外接白框,用于提升识别率,文字框没有正确框住所有文字时,增加此值。
    ocrEngine.boxScoreThresh = boxScoreThresh //文字框置信度门限,文字框没有正确框住所有文字时,减小此值
    ocrEngine.boxThresh = boxThresh //请自行试验
    ocrEngine.unClipRatio = unClipRatio //单个文字框大小倍率,越大时单个文字框越大
    ocrEngine.doAngle = doAngle //启用(1)/禁用(0) 文字方向检测,只有图片倒置的情况下(旋转90~270度的图片),才需要启用文字方向检测
    ocrEngine.mostAngle = mostAngle //启用(1)/禁用(0) 角度投票(整张图片以最大可能文字方向来识别),当禁用文字方向检测时,此项也不起作用

    //------- start detect -------
    val ocrResult =
        ocrEngine.detect(imagePath, maxSideLen = maxSideLen) //按图像长边进行总体缩放,放大增加识别耗时但精度更高,缩小减小耗时但精度降低,maxSideLen=0代表不缩放
    //使用native方法,可以让OcrEngine成为单例
    /*val ocrResult =
        ocrEngine.detect(imagePath, padding, maxSideLen, boxScoreThresh, boxThresh, unClipRatio, doAngle, mostAngle)*/
    //------- print result -------
    println("识别结果: "+ ocrResult.toString())
    return
}

RapidOcrOnnxJvm (推荐)

官方说明项目- https://github.com/RapidAI/RapidOcrOnnxJvm
dll库项目 - https://github.com/RapidAi/RapidOcrOnnx/releases
模型下载- https://github.com/RapidAI/RapidOcrOnnx/releases/tag/1.2.2

object INSTANCE {
    val log = LoggerFactory.getLogger(INSTANCE::class.java)
    val ocrEngine = OcrEngine()
    init {
        val modelsDir = System.getProperty("user.dir") + "\\run\\models_onnx"
        println("加载模型目录 : "+modelsDir)
        //注意 他这里需要模型后缀了, 我靠
        val detName = "ch_PP-OCRv3_det_infer.onnx"
        val clsName = "ch_ppocr_mobile_v2.0_cls_infer.onnx"
        val recName = "ch_PP-OCRv3_rec_infer.onnx"
        val keysName = "ppocr_keys_v1.txt"
        val numThread = 4;
        ocrEngine.setNumThread(numThread)

        //------- init Logger -------
        ocrEngine.initLogger(
            isConsole = false,
            isPartImg = false,
            isResultImg = false
        )
        //------- init Models -------
        val initModelsRet = ocrEngine.initModels(modelsDir, detName, clsName, recName, keysName)
        if (!initModelsRet) {
            log.error("模型初始化失败")
        }else{
            log.info("模型初始化成功")
        }
    }
}

更换模型

更多模型可以在官网 https://rapidai.github.io/RapidOCRDocs/model_list/#_1 下载(Onnx格式)
在PC端识别用到的就是:

val detName = "ch_PP-OCRv4_det_infer.onnx"  
val recName = "ch_PP-OCRv4_rec_infer.onnx"

ppocr_keys_v1.txt 用原来的即可

posted @ 2025-12-02 20:52  daidaidaiyu  阅读(0)  评论(0)    收藏  举报