LEADTOOLS SDK使用自动识别管理器的多线程OCR - C DLL

使用自动识别管理器的多线程 OCR - Windows C DLL

本教程介绍如何在 C/C++ Windows API 应用程序中使用 LEADTOOLS SDK 对 OCR 引擎进行多线程并行处理。

概述 
概括本教程介绍如何使用 Windows C DLL 应用程序中的 LEAD 自动识别管理器对 OCR 引擎进行多线程处理。
完成时间45分钟
Visual Studio 项目下载教程项目 (19 KB)
平台Windows C DLL 应用程序
集成开发环境Visual Studio 2017、2019、2022
开发许可证下载 LEADTOOLS
尝试使用其他语言

所需知识

在使用自动识别管理器 - Windows C DLL教程进行多线程 OCR 之前,请先通过查看添加引用和设置许可证教程熟悉创建项目的基本步骤。

创建项目并添加 LEADTOOLS 引用

从“添加引用”和“设置许可证”教程中创建的 64 位 Windows API 项目的副本开始。 Start with a copy of the 64-bit Windows API project created in the Add References and Set a License tutorial. 如果该项目不可用,请按照该教程中的步骤创建它。

要使用 LEADTOOLS OCR 功能,需要额外的头文件和 DLL 文件。打开预编译头文件(或pch.hstdafx.h取决于所使用的 Visual Studio 版本)并添加以下几行:

#include "C:\LEADTOOLS23\Include\ltocr.h" 
#pragma comment (lib, "C:\\LEADTOOLS23\\Lib\\CDLL\\x64\\Ltocr_x.lib") // OCR support 

注意:有关 OCR 应用程序所需的 DLL 文件的完整列表,请参阅应用程序中包含的文件

设置许可证文件

许可证用于解锁项目所需的功能。必须在调用任何工具包函数之前设置许可证。有关详细信息(包括不同平台的教程),请参阅设置运行时许可证

运行时许可证有两种类型:

  • 评估许可证,在下载评估工具包时获得。它允许对工具包进行评估。
  • 部署许可证。如果需要部署许可证文件和开发者密钥,请参阅获取许可证

注意:在添加引用和设置许可证教程中更详细地介绍了添加 LEADTOOLS 引用和设置许可证

添加多线程OCR代码

现在已经添加了 LEADTOOLS 引用并设置了许可证,可以开始编码了。

以下步骤适用于 Visual Studio 2019;对于其他版本的 Visual Studio,它们可能有所不同。

转到解决方案资源管理器并双击资源文件 (.rc)。

展开资源树中的菜单,双击菜单资源即可在设计器界面中打开。

在“Exit”项下方的空白处,点击并输入“Multithread &OCR”。将新项拖到“Exit”上方。这会导致该项的 ID 变为ID_FILE_MULTITHREADOCR

转到项目的主 CPP 文件,然后导航到WndProc主窗口函数。在switch (wmId)语句下方(即WM_COMMAND案例下方),添加一个新案例:

switch (wmId) 
{ 
case ID_FILE_MULTITHREADOCR: 
{ 
   TCHAR szFolderIn[1024] = TEXT(""); // Input files location 
   // Choose input files folder 
   if (SUCCESS != GetSourceFolder(hWnd, szFolderIn, ARRAYSIZE(szFolderIn))) 
      break; 
   float time1 = ProcessFolder(hWnd, szFolderIn, false, false); 
   if (time1 < 0) 
      break; 
   float time2 = ProcessFolder(hWnd, szFolderIn, false, true); 
   if (time2 < 0) 
      break; 
   float time3 = ProcessFolder(hWnd, szFolderIn, true, false); 
   if (time3 < 0) 
      break; 
   float time4 = ProcessFolder(hWnd, szFolderIn, true, true); 
   if (time4 < 0) 
      break; 
   TCHAR szResult[2000]; 
   _stprintf_s(szResult, ARRAYSIZE(szResult), TEXT("Test times in seconds:\n" 
      "%.1f\tBoth sequential\n" 
      "%.1f\tParallel pages\n" 
      "%.1f\tParallel documents\n" 
      "%.1f\tBoth parallel"), time1, time2, time3, time4); 
   MessageBox(hWnd, szResult, TEXT("Recognition Time"), MB_ICONINFORMATION); 
} 
   break; 
// Keep rest of the code as is 

LEADTOOLS OCR 自动识别管理器支持在处理作业时使用多个线程,可以使用L_OcrAutoRecognizeManagerOptions::UseThreads结构成员启用该功能。

也可以在自己的线程中执行每个作业,这在下面的代码中使用CreateThread()函数完成。

在函数上方添加两个名为ProcessFolder和 的函数,并在其中添加以下代码:RecognizeTifWndProc

struct RECOGNIZE_PARAMS 
{ 
   L_OcrAutoRecognizeManager autoRecognizeManager; 
   TCHAR* pszTifFile; 
   TCHAR* pszPdfFile; 
}; 
 
DWORD WINAPI RecognizeTif(void* pParam) 
{ 
   RECOGNIZE_PARAMS* pRecParam = (RECOGNIZE_PARAMS*)pParam; 
   L_OcrAutoRecognizeManager_Run(pRecParam->autoRecognizeManager, pRecParam->pszTifFile, pRecParam->pszPdfFile, DOCUMENTFORMAT_PDF, NULL); 
   return 0; 
} 
 
// 
// FUNCTION: ProcessFolder 
// Return Value: 
//    < 0   : Error 
//    >= 0  : Elapsed Time 
// 
float ProcessFolder(HWND hWnd, TCHAR* pszFolderIn, bool parallelPages, bool parallalDocuments) 
{ 
   TCHAR szFolderSearch[1000] = TEXT(""); // Input files search location and pattern 
   _tcscpy_s(szFolderSearch, ARRAYSIZE(szFolderSearch), pszFolderIn); 
   _tcscat_s(szFolderSearch, ARRAYSIZE(szFolderSearch), TEXT("\\*.tif")); 
 
   WIN32_FIND_DATA FindFileData = { 0 }; 
   HANDLE hFind = FindFirstFile(szFolderSearch, &FindFileData); 
   if (INVALID_HANDLE_VALUE == hFind) 
   { 
      MessageBox(hWnd, TEXT("No TIF files found in folder"), TEXT("LEADTOOLS Demo"), MB_ICONERROR); 
      return -1; 
   } 
 
   L_OcrEngine ocrEngine = NULL; 
   L_OcrAutoRecognizeManager autoRecognizeManager = NULL; 
   L_OcrAutoRecognizeManagerOptions autoRecognizeOptions = { 0 }; 
   L_OcrDocumentManager ocrDocumentManager = NULL; 
 
   if (L_OcrEngineManager_CreateEngine(L_OcrEngineType_LEAD, &ocrEngine) != SUCCESS) 
      return -1; 
   L_OcrEngine_Startup(ocrEngine, NULL, TEXT("C:\\LEADTOOLS23\\Bin\\Common\\OcrLEADRuntime")); 
   L_OcrEngine_GetAutoRecognizeManager(ocrEngine, &autoRecognizeManager); 
   autoRecognizeOptions.StructSize = sizeof L_OcrAutoRecognizeManagerOptions; 
   L_OcrAutoRecognizeManager_GetOptions(autoRecognizeManager, &autoRecognizeOptions); 
   autoRecognizeOptions.UseThreads = parallelPages; 
   // Deskew and auto-orient all pages before recognition 
   autoRecognizeOptions.PreprocessPageCommands = L_OcrAutoPreprocessPageCommands_Deskew | L_OcrAutoPreprocessPageCommands_Rotate; 
   L_OcrAutoRecognizeManager_SetOptions(autoRecognizeManager, &autoRecognizeOptions); 
   // Create PDFs with Image/Text option 
   L_OcrEngine_GetDocumentManager(ocrEngine, &ocrDocumentManager); 
   DOCWRTPDFOPTIONS pdfOptions; 
   pdfOptions.Options.uStructSize = sizeof DOCWRTPDFOPTIONS; 
   L_OcrDocumentManager_GetFormatOptions(ocrDocumentManager, DOCUMENTFORMAT_PDF, &pdfOptions.Options); 
   // Set the specific PDF options we want 
   pdfOptions.bImageOverText = true; 
   pdfOptions.PdfProfile = DOCWRTPDFPROFILE_PDF; 
   L_OcrDocumentManager_SetFormatOptions(ocrDocumentManager, DOCUMENTFORMAT_PDF, &pdfOptions.Options); 
   ULONGLONG timeStart = GetTickCount64(); 
   int nThreadCount = 0; 
   HANDLE hThreads[MAXIMUM_WAIT_OBJECTS] = { 0 }; 
   do 
   { 
      if (nThreadCount >= MAXIMUM_WAIT_OBJECTS) 
      { 
         MessageBox(hWnd, TEXT("Too many documents for this test"), TEXT("LEADTOOLS Demo"), MB_ICONERROR); 
         return -1; 
      } 
      TCHAR szTifFile[1024] = TEXT(""); // Input file full location and name 
      _tcscpy_s(szTifFile, ARRAYSIZE(szTifFile), pszFolderIn); 
      _tcscat_s(szTifFile, ARRAYSIZE(szTifFile), TEXT("\\")); 
      _tcscat_s(szTifFile, ARRAYSIZE(szTifFile), FindFileData.cFileName); 
      TCHAR szPdfFile[1024] = TEXT(""); // Output file full location and name 
      _tcscpy_s(szPdfFile, ARRAYSIZE(szPdfFile), szTifFile); 
      _tcscat_s(szPdfFile, ARRAYSIZE(szPdfFile), TEXT(".pdf")); 
      RECOGNIZE_PARAMS param = { 0 }; 
      param.autoRecognizeManager = autoRecognizeManager; 
      param.pszTifFile = szTifFile; 
      param.pszPdfFile = szPdfFile; 
      if (parallalDocuments) // Call in a new thread 
      { 
         hThreads[nThreadCount] = CreateThread(NULL, 0, RecognizeTif, &param, 0, NULL); 
         nThreadCount++; 
      } 
      else // Sequential documents, call directly 
         RecognizeTif(&param); 
 
   } while (FindNextFile(hFind, &FindFileData) != 0); 
 
   if (nThreadCount > 0) 
   { 
      // Do NOT proceed to shutdown OCR before all threads exit 
      WaitForMultipleObjects(nThreadCount, hThreads, TRUE, INFINITE); 
      // Free all threads handles 
      while (nThreadCount > 0) 
      { 
         nThreadCount--; 
         CloseHandle(hThreads[nThreadCount]); 
      } 
   } 
   ULONGLONG timeElapsed = GetTickCount64() - timeStart; 
   L_OcrEngine_Shutdown(ocrEngine); 
   L_OcrEngine_Destroy(ocrEngine); 
   return timeElapsed / 1000.0; 
} 

GetSourceFolder()函数可以是任何使用szFolderIn包含 TIFF 文件的有效文件夹名称填充变量的函数。要显示“选择文件夹”对话框以获取文件夹名称,请添加以下代码:

#include <shobjidl_core.h> 
L_INT GetSourceFolder(HWND hWnd, TCHAR* pszFolder, rsize_t  string_size) 
{ 
   L_INT nRet = FAILURE; 
   IFileOpenDialog* pFileOpenDialog = NULL; 
   IShellItem* pShellItem = NULL; 
   CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_IFileOpenDialog, (void**)&pFileOpenDialog); 
   if (pFileOpenDialog) 
   { 
      pFileOpenDialog->SetOptions(FOS_PICKFOLDERS); 
      if (SUCCEEDED(pFileOpenDialog->Show(hWnd))) 
      { 
         pFileOpenDialog->GetResult(&pShellItem); 
         LPWSTR pFolder = NULL; 
         pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pFolder); 
         if (pFolder) 
         { 
            _tcscpy_s(pszFolder, string_size, pFolder); 
            CoTaskMemFree(pFolder); 
            nRet = SUCCESS; 
         } 
      } 
   } 
   if (pShellItem) 
      pShellItem->Release(); 
   if (pFileOpenDialog) 
      pFileOpenDialog->Release(); 
   return nRet; 
} 

运行项目

按F5或选择“调试”->“开始调试”来运行项目。

如果正确执行这些步骤,应用程序将运行并允许用户选择输入文件夹。然后,应用程序将处理输入文件夹中的每个 TIFF 文件,并据此创建一个新的 PDF 文件。此过程将使用不同的顺序和并行处理组合重复四次。

应用程序显示OCR进度

注意:在图片所示的测试中,并行处理目录文档以及每个文档的页面时获得了最佳结果。但是,不同的图像集或具有不同 CPU 核心数的不同计算机可能会产生不同的结果。因此,务必在应用程序将要使用的实际硬件上使用代表用例的实际图像进行测试。

本教程展示了如何创建使用 LEAD OCR 引擎的 Windows C++ OCR 应用程序,以比较使用不同的顺序和并行处理技术时的性能。

参见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值