Delphi调用百度飞桨(PaddleOCR)OCR模型库识别验证码

PaddleOCR是百度开源的超轻量级OCR模型库,本文旨在分享如何通过Delphi使用其框架进行验证码识别。

调用事例基于Git上(https://gitee.com/raoyutian/paddle-ocrsharp)项目开源代码C++使用PaddleOCR中的代码转化而来

unit uPPOCRApi;

interface

/// <summary>
/// OCR识别参数
/// </summary>
type
  OCRParameter = packed record
    // 通用参数
    use_gpu: Boolean; // 是否使用GPU;默认false
    gpu_id: Integer; // GPU id,使用GPU时有效;默认0;
    gpu_mem: Integer; // 申请的GPU内存;默认4000
    cpu_math_library_num_threads: Integer; // CPU预测时的线程数,在机器核数充足的情况下,该值越大,预测速度越快;默认10
    enable_mkldnn: Boolean; // 是否使用mkldnn库;默认true

    // 前向相关
    det: Boolean; // 是否执行文字检测;默认true
    rec: Boolean; // 是否执行文字识别;默认true
    cls: Boolean; // 是否执行文字方向分类;默认false

    // 检测模型相关
    max_side_len: Integer; // 输入图像长宽大于960时,等比例缩放图像,使得图像最长边为960,;默认960
    det_db_thresh: Single; // 用于过滤DB预测的二值化图像,设置为0.-0.3对结果影响不明显;默认0.3
    det_db_box_thresh: Single; // DB后处理过滤box的阈值,如果检测存在漏框情况,可酌情减小;默认0.5
    det_db_unclip_ratio: Single; // 表示文本框的紧致程度,越小则文本框更靠近文本;默认1.6
    use_dilation: Boolean; // 是否在输出映射上使用膨胀,默认false
    det_db_score_mode: Boolean; // 1:使用多边形框计算bbox score,0:使用矩形框计算。矩形框计算速度更快,多边形框对弯曲文本区域计算更准确。
    visualize: Boolean; // 是否对结果进行可视化,为1时,预测结果会保存在output字段指定的文件夹下和输入图像同名的图像上。默认false

    // 方向分类器相关
    use_angle_cls: Boolean; // 是否使用方向分类器,默认false
    cls_thresh: Single; // 方向分类器的得分阈值,默认0.9
    cls_batch_num: Integer; // 方向分类器batchsize,默认1

    // 识别模型相关
    rec_batch_num: Integer; // 识别模型batchsize,默认6
    rec_img_h: Integer; // 识别模型输入图像高度,默认48
    rec_img_w: Integer; // 识别模型输入图像宽度,默认320

    show_img_vis: Boolean; // 是否显示预测结果,默认false
    use_tensorrt: Boolean; // 使用GPU预测时,是否启动tensorrt,默认false

    ///初始化属性默认值
    procedure InitPropertyDefaultValue;
  end;

  /// <summary>
  /// 表格识别参数
  /// </summary>
  StructureParameter = record
    OCRParameter: OCRParameter;
    table_max_len: Integer;  // 输入图像长宽大于488时,等比例缩放图像,默认488
    merge_no_span_structure: Boolean;  // 是否合并空单元格,默认true
    table_batch_num: Integer;  // 批量识别数量,默认1
  end;

  /// <summary>
  /// 获取最后一次错误信息
  /// </summary>
  /// <returns></returns>
  function GetError: PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 是否使用单字节编码(适用于go,rust),C#,Python不用打开此开关
  /// </summary>
  /// <param name="useANSI"></param>
  procedure EnableANSIResult(useANSI: Boolean); stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 文字识别引擎初始化
  /// </summary>
  /// <param name="det_infer">det模型全路径</param>
  /// <param name="cls_infer">cls模型全路径</param>
  /// <param name="rec_infer">rec模型全路径</param>
  /// <param name="keys">字典全路径</param>
  /// <param name="parameter">识别参数对象</param>
  /// <returns></returns>
  function Initialize(det_infer: PAnsiChar; cls_infer: PAnsiChar; rec_infer: PAnsiChar; keys: PAnsiChar; parameter: OCRParameter): Boolean; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// PaddleOCREngine引擎初始化
  /// </summary>
  /// <param name="det_infer">det模型全路径</param>
  /// <param name="cls_infer">cls模型全路径</param>
  /// <param name="rec_infer">rec模型全路径</param>
  /// <param name="keys">字典全路径</param>
  /// <param name="parameterjson">识别参数对象json字符串</param>
  /// <returns></returns>
  function Initializejson(modelPath_det_infer: PAnsiChar; modelPath_cls_infer: PAnsiChar; modelPath_rec_infer: PAnsiChar; keys: PAnsiChar; parameterjson: PAnsiChar): Boolean; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 文本检测识别-图像文件路径
  /// </summary>
  /// <param name="imagebytedata">图像文件路径</param>
  /// <returns></returns>
  function Detect(imagefile: PAnsiChar): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 文本检测识别-OpenCV Mat
  /// </summary>
  /// <param name="cvmat">Mat对象</param>
  /// <returns></returns>
  //function DetectMat(var cvmat: TMat): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 文本检测识别-图像字节流
  /// </summary>
  /// <param name="imagebytedata">图像字节流</param>
  /// <param name="size">图像字节流长度</param>
  /// <returns></returns>
  function DetectByte(imagebytedata: PAnsiChar; var size: Integer): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 文本检测识别-图像字节流
  /// </summary>
  /// <param name="img">图像地址</param>
  /// <param name="nWidth">图像宽度</param>
  /// <param name="nHeight">图像高度</param>
  /// <param name="nChannel">图像通道数</param>
  /// <returns></returns>
  function DetectByteData(img: PAnsiChar; nWidth: Integer; nHeight: Integer; nChannel: Integer): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 文本检测识别-图像base64
  /// </summary>
  /// <param name="imagebase64">图像base64</param>
  /// <returns></returns>
  function DetectBase64(imagebase64: PAnsiChar): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 释放引擎对象
  /// </summary>
  procedure FreeEngine; stdcall; external 'PaddleOCR.dll';

  {/// <summary>
  /// 表格识别引擎初始化
  /// </summary>
  /// <param name="modelPath_det_infer">det模型全路径</param>
  /// <param name="modelPath_rec_infer">cls模型全路径</param>
  /// <param name="keys">字典全路径</param>
  /// <param name="table_model_dir">表格模型全路径</param>
  /// <param name="table_char_dict_path">表格字典全路径</param>
  /// <param name="parameter">参数对象</param>
  /// <returns></returns>
  function StructureInitialize(modelPath_det_infer: PAnsiChar; modelPath_rec_infer: PAnsiChar; keys: PAnsiChar; table_model_dir: PAnsiChar; table_char_dict_path: PAnsiChar; parameter: StructureParameter): Boolean; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 表格识别引擎初始化json格式
  /// </summary>
  /// <param name="modelPath_det_infer">det模型全路径</param>
  /// <param name="modelPath_rec_infer">cls模型全路径</param>
  /// <param name="keys">字典全路径</param>
  /// <param name="table_model_dir">表格模型全路径</param>
  /// <param name="table_char_dict_path">表格字典全路径</param>
  /// <param name="parameterjson">参数对象json格式</param>
  /// <returns></returns>
  function StructureInitializejson(modelPath_det_infer: PAnsiChar; modelPath_rec_infer: PAnsiChar; keys: PAnsiChar; table_model_dir: PAnsiChar; table_char_dict_path: PAnsiChar; parameterjson: PAnsiChar): Boolean; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 表格识别
  /// </summary>
  /// <param name="imagefile">文件路径</param>
  /// <returns></returns>
  function GetStructureDetectFile(imagefile: PAnsiChar): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  // <summary>
  // 表格识别
  // </summary>
  // <param name="cvmat">opencv Mat对象</param>
  // <returns></returns>
  // function GetStructureDetectMat(var cvmat: TMat): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 表格识别
  /// </summary>
  /// <param name="imagebytedata">图像字节流</param>
  /// <param name="size">图像字节流长度</param>
  /// <returns></returns>
  function GetStructureDetectByte(imagebytedata: PAnsiChar; var size: Integer): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 表格识别
  /// </summary>
  /// <param name="imagebase64">图像base64</param>
  /// <returns></returns>
  function GetStructureDetectBase64(imagebase64: PAnsiChar): PAnsiChar; stdcall; external 'PaddleOCR.dll';

  /// <summary>
  /// 释放引擎对象
  /// </summary>
  procedure FreeStructureEngine; stdcall; external 'PaddleOCR.dll';}

implementation

{ OCRParameter }

procedure OCRParameter.InitPropertyDefaultValue;
begin
  use_gpu := False;
  gpu_id := 0;
  gpu_mem := 4000;
  cpu_math_library_num_threads := 10;
  enable_mkldnn := True;

  det := True;
  rec := True;
  cls := False;

  max_side_len := 960;
  det_db_thresh := 0.3;
  det_db_box_thresh := 0.5;
  det_db_unclip_ratio := 1.6;
  use_dilation := False;
  det_db_score_mode := True;
  visualize := False;

  use_angle_cls := False;
  cls_thresh := 0.9;
  cls_batch_num := 1;

  rec_batch_num := 6;
  rec_img_h := 48;
  rec_img_w := 320;
  show_img_vis := False;
  use_tensorrt := False;
end;

end.

调用代码

function GetFiles(const Directory: string; Filenames: TStrings): Boolean;
var
  h: THandle;
  FindData: TWin32FindData;
begin
  Result := False;
  h := FindFirstFile(PChar(Directory + '\*.*'), FindData);
  if h <> INVALID_HANDLE_VALUE then
  begin
    repeat
      if (StrComp(FindData.cFileName, '.') <> 0) and (StrComp(FindData.cFileName, '..') <> 0) then
      begin
        Filenames.Add(Directory + '\' + FindData.cFileName);
        if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
          GetFiles(Filenames[Filenames.Count - 1], Filenames);
      end;
    until not FindNextFile(h, FindData);
    Windows.FindClose(h);
  end;
  Result := True;
end;

procedure TMainForm.Button1Click(Sender: TObject);
var
  parameter: OCRParameter;
  sPath, cls_infer, rec_infer, det_infer, ocrkeys, imagepath: string;
  images: TStringList;
  i: Integer;
  start, finish: TDateTime;
  duration: Int64;
  resultText: string;
  sparameterjson: string;
begin
  // Set up paths and parameters
  parameter.InitPropertyDefaultValue;
  sPath := ExtractFilePath(ParamStr(0));

  cls_infer := sPath + 'inference\ch_ppocr_mobile_v2.0_cls_infer';
  rec_infer := sPath + 'inference\ch_PP-OCRv4_rec_infer';
  det_infer := sPath + 'inference\ch_PP-OCRv4_det_infer';
  ocrkeys := sPath + 'inference\ppocr_keys.txt';
  imagepath := sPath + 'images';

  // Get image paths
  images := TStringList.Create;
  try
    if getFiles(imagepath, images) and (images.Count > 0) then
    begin
      // Initialize OCR engine
      EnableANSIResult(True);
      Initialize(PAnsiChar(AnsiString(det_infer)), PAnsiChar(AnsiString(cls_infer)),
                 PAnsiChar(AnsiString(rec_infer)), PAnsiChar(AnsiString(ocrkeys)), parameter);

      {Initializejson(PAnsiChar(AnsiString(det_infer)), PAnsiChar(AnsiString(cls_infer)),
                 PAnsiChar(AnsiString(rec_infer)), PAnsiChar(AnsiString(ocrkeys)), PAnsiChar(AnsiString(sparameterjson)));}

      // Perform OCR on each image
      for i := 0 to images.Count - 1 do
      begin
        start := Now;
        resultText := string(Detect(PAnsiChar(AnsiString(images[i]))));
        mmo_Log.Lines.Add(resultText);
        finish := Now;
        //duration := MillisecondsBetween(finish, start);
        //Writeln(IntToStr(duration) + 'ms');
      end;
    end;
  finally
    images.Free;
  end;

  // Free OCR engine
  FreeEngine;
end;

 项目核心组件PaddleOCR.dll,由C++编写,只支持64位程序,只能在Delphi XE2及以上版本64位平台调用。

年前接到一个爬虫任务,由于平台登录有验证码校验,必须登录该平台后才能爬取数据,该平台验证码如下,是计算式验证码带干扰线的。

   

验证码是gif格式,转成Bmp后,对图片进行二值化后的结果

之后调用PaddleOCR.dll进行识别,识别结果准确率还是很高的,针对每张验证码图片识别结果返回的是一个json串。

通过PaddleOCR框架识别验证码,省去了针对验证码做字模库的繁杂步骤,当然识别前提是针对验证码图片进行了相应的过滤步骤,使图片相对清晰,该框架用途不限于此,感兴趣的朋友可参照上边调用源码去解锁更多用途。

有爬虫及验证码识别业务的朋友,可以站内联系合作。                                                                   

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值