#include-once
#AutoIt3Wrapper_UseX64 = Y
#include "JSON_Dictionary.au3"
;==================== 常量定义 ====================
Global Enum $OCR_SUCCESS = 0, $OCR_ORT_ERROR, $OCR_IO_ERROR, $OCR_IMAGE_ERROR, _
$OCR_SESSION_NOT_INIT, $OCR_INVALID_MODEL_PATH, $OCR_FILE_NOT_FOUND, _
$OCR_INVALID_ENCODING, $OCR_INVALID_PARAM, $OCR_MEM_ALLOC_FAIL, _
$OCR_INVALID_IMG_FORMAT, $OCR_TIMEOUT
;==================== 全局变量 ====================
Global $__g_hOCR = Null ; OCR实例指针
Global $__g_hDLL = -1 ; DLL句柄
;==================== 接口函数 ====================
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_Create
; 描述 ..........: 创建OCR实例并初始化DLL环境
; 语法 ..........: _OCR_Create()
; 参数 ..........: 无
; 返回值 ........: 成功 - 返回True
; 失败 - 返回False,设置@error:
; @error = 1 - 加载DLL失败
; @error = 2 - 创建OCR实例失败
; 说明 ..........: 必须先于其他函数调用
; ==============================================================================
Func _OCR_Create()
$__g_hDLL = DllOpen("paddle.dll")
If $__g_hDLL = -1 Then Return SetError(1, 0, False)
Local $aRet = DllCall($__g_hDLL, "ptr:cdecl", "ocr_create")
If @error Then
DllClose($__g_hDLL)
Return SetError(2, @error, False)
EndIf
$__g_hOCR = $aRet[0]
Return True
EndFunc ;==>_OCR_Create
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_InitModels
; 描述 ..........: 初始化OCR模型
; 语法 ..........: _OCR_InitModels($sDetModel, $sClsModel, $sRecModel, $sKeyPath[, $iThreads = 4])
; 参数 ..........: $sDetModel - 检测模型路径(det.onnx)
; $sClsModel - 方向分类模型路径(cls.onnx)
; $sRecModel - 识别模型路径(rec.onnx)
; $sKeyPath - 字符集文件路径(keys.txt)
; $iThreads - [可选] 线程数(默认4,范围1-16)
; 返回值 ........: 成功 - 返回$OCR_SUCCESS
; 失败 - 返回错误代码,可通过_OCR_GetErrorMessage获取描述
; ==============================================================================
Func _OCR_InitModels($sDetModel, $sClsModel, $sRecModel, $sKeyPath, $iThreads = 4)
If $__g_hOCR = Null Then Return SetError($OCR_SESSION_NOT_INIT, 0, $OCR_SESSION_NOT_INIT)
Local $aRet = DllCall($__g_hDLL, "int:cdecl", "ocr_init", _
"ptr", $__g_hOCR, _
"wstr", $sDetModel, _
"wstr", $sClsModel, _
"wstr", $sRecModel, _
"wstr", $sKeyPath, _
"int", $iThreads)
Return SetError(@error, 0, $aRet[0])
EndFunc ;==>_OCR_InitModels
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_DetectImage
; 描述 ..........: 执行OCR识别
; 语法 ..........: _OCR_DetectImage($sImgPath[, $iPadding = 50[, $iMaxSize = 1024[, $fBoxThresh = 0.3[, $fUnClipRatio = 1.6[, $bCheckAngle = True[, $bMostAngle = False]]]]])
; 参数 ..........: $sImgPath - 要识别的图像路径
; $iPadding - [可选] 图像填充尺寸(默认50)
; $iMaxSize - [可选] 最大边长限制(默认1024)
; $fBoxThresh - [可选] 文本框阈值(默认0.3)
; $fUnClipRatio - [可选] 文本框扩展比例(默认1.6)
; $bCheckAngle - [可选] 是否检测文字方向(默认True)
; $bMostAngle - [可选] 是否使用主要方向(默认False)
; 返回值 ........: 成功 - 返回结果指针(需用_OCR_GetResult解析)
; 失败 - 返回0,设置@error为错误代码
; ==============================================================================
Func _OCR_DetectImage($sImgPath, $iPadding = 50, $iMaxSize = 1024, $fBoxThresh = 0.3, $fUnClipRatio = 1.6, $bCheckAngle = True, $bMostAngle = False)
If $__g_hOCR = Null Then Return SetError($OCR_SESSION_NOT_INIT, 0, 0)
Local $aRet = DllCall($__g_hDLL, "ptr:cdecl", "ocr_detect", _
"ptr", $__g_hOCR, _
"wstr", $sImgPath, _
"uint", $iPadding, _
"uint", $iMaxSize, _
"float", 0.5, _
"float", $fBoxThresh, _
"float", $fUnClipRatio, _
"bool", $bCheckAngle, _
"bool", $bMostAngle)
If @error Then Return SetError(@error, 0, 0)
Return $aRet[0]
EndFunc ;==>_OCR_DetectImage
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_GetResult
; 描述 ..........: 获取OCR识别结果
; 语法 ..........: _OCR_GetResult(ByRef $pResult)
; 参数 ..........: $pResult - _OCR_DetectImage返回的结果指针
; 返回值 ........: 成功 - 返回JSON字符串
; 失败 - 返回空字符串,设置@error:
; @error = 1 - 无效指针
; @error = 2 - 结果转换失败
; 说明 ..........: 使用后必须调用_OCR_FreeResult释放内存
; ==============================================================================
Func _OCR_GetResult(ByRef $pResult)
If $pResult = 0 Then Return SetError(1, 0, "")
Local $tResult = DllStructCreate("ptr text; uint64 length; int error_code;", $pResult)
Local $iErrorCode = DllStructGetData($tResult, "error_code")
If $iErrorCode <> $OCR_SUCCESS Then Return SetError($iErrorCode, 0, "")
Local $sTextPtr = DllStructGetData($tResult, "text")
Local $iLength = DllStructGetData($tResult, "length")
If $iLength = 0 Then Return SetError(2, 0, "")
Local $tBuffer = DllStructCreate("byte[" & $iLength * 2 & "]", $sTextPtr)
Return BinaryToString(DllStructGetData($tBuffer, 1), $SB_UTF16LE)
EndFunc ;==>_OCR_GetResult
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_FreeResult
; 描述 ..........: 释放OCR结果内存
; 语法 ..........: _OCR_FreeResult(ByRef $pResult)
; 参数 ..........: $pResult
; 返回值 ........: 无
; ==============================================================================
Func _OCR_FreeResult(ByRef $pResult)
If $pResult = 0 Then Return
DllCall($__g_hDLL, "none:cdecl", "ocr_free_result", "ptr", $pResult)
$pResult = 0
EndFunc ;==>_OCR_FreeResult
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_Release
; 描述 ..........: 释放所有OCR资源
; 语法 ..........: _OCR_Release()
; 参数 ..........: 无
; 返回值 ........: 无
; 说明 ..........: 程序退出前必须调用
; ==============================================================================
Func _OCR_Release()
If $__g_hOCR Then
DllCall($__g_hDLL, "none:cdecl", "ocr_destroy", "ptr", $__g_hOCR)
$__g_hOCR = Null
EndIf
If $__g_hDLL <> -1 Then
DllClose($__g_hDLL)
$__g_hDLL = -1
EndIf
EndFunc ;==>_OCR_Release
; #FUNCTION# ===================================================================
; 名称 ..........: _OCR_GetErrorMessage
; 描述 ..........: 获取错误码描述
; 语法 ..........: _OCR_GetErrorMessage($iErrorCode)
; 参数 ..........: $iErrorCode - 错误代码
; 返回值 ........: 错误描述字符串
; ==============================================================================
Func _OCR_GetErrorMessage($iErrorCode)
Local Static $aErrors[] = [ _
"成功", "ORT引擎错误", "文件IO错误", "图像处理错误", _
"未初始化实例", "无效模型路径", "文件不存在", _
"编码错误", "参数错误", "内存分配失败", _
"图像格式错误", "操作超时"]
Return ($iErrorCode >= 0 And $iErrorCode < UBound($aErrors)) ? $aErrors[$iErrorCode] : "未知错误"
EndFunc ;==>_OCR_GetErrorMessage
; ==============================================================================
#include <Timers.au3>
If Not _OCR_Create() Then
MsgBox(0x10, "错误", "初始化失败:" & _OCR_GetErrorMessage(@error))
Exit
EndIf
Local $iRet = _OCR_InitModels( _
@ScriptDir & "\models\ch_PP-OCRv4_det_infer.onnx", _
@ScriptDir & "\models\ch_ppocr_mobile_v2.0_cls_infer.onnx", _
@ScriptDir & "\models\ch_PP-OCRv4_rec_infer.onnx", _
@ScriptDir & "\models\ppocr_keys_v1.txt")
If $iRet <> $OCR_SUCCESS Then
MsgBox(0x10, "错误", "模型加载失败:" & _OCR_GetErrorMessage($iRet))
_OCR_Release()
Exit
EndIf
Local $hTimer = _Timer_Init()
Local $pResult = _OCR_DetectImage(@ScriptDir & "\TEST.jpg")
If @error Then
MsgBox(0x16, "错误", "识别失败:" & _OCR_GetErrorMessage(@error))
_OCR_Release()
Exit
EndIf
Local $sJSON = _OCR_GetResult($pResult)
If @error Then
MsgBox(0x10, "错误", "结果解析失败:" & _OCR_GetErrorMessage(@error))
Else
Local $oResult = _JSON_Parse($sJSON)
Local $aBlocks = _JSON_Get($oResult, ".text_blocks")
For $i = 0 To UBound($aBlocks) - 1
Local $sText = _JSON_Get($aBlocks[$i], ".text")
Local $fScore = _JSON_Get($aBlocks[$i], ".text_score")
Local $aPoints = _JSON_Get($aBlocks[$i], ".box_points")
Local $sCoords = ""
For $j = 0 To UBound($aPoints) - 1
$sCoords &= StringFormat("(%d,%d)", _
_JSON_Get($aPoints[$j], ".x"), _
_JSON_Get($aPoints[$j], ".y"))
Next
ConsoleWrite(StringFormat("块 %02d | 文本: ""%s"" | 置信度: %.4f | 坐标: %s", $i + 1, StringLeft($sText, 100), Round($fScore, 4), $sCoords) & @CRLF)
Next
EndIf
ConsoleWrite("耗时:" & Round(_Timer_Diff($hTimer), 2) & "ms" & @CRLF)
_OCR_FreeResult($pResult)
_OCR_Release()