跳轉到主要內容
此情境用於處理紙本文件,並將其存入數位檔案庫,尤其適合建立合約、專案文件、發票、證明等文件的歸檔。 在此處理情境中,紙本文件會轉換為不可編輯的數位副本,並以可搜尋的格式保留文件中的所有資訊。經過這類處理後,即可在電子檔案庫中透過全文檢索輕鬆找到文件、複製文件中的文字片段,以及透過電子郵件傳送或列印文件。 若要建立數位副本,文件首先需要經過數個處理階段,而每個階段各有其特點:
  1. 掃描影像的預處理
掃描影像在辨識前可能需要先進行某些預處理,例如掃描文件中有背景雜訊、文字傾斜、色彩反相、黑邊、方向錯誤或解析度不正確等情況。
  1. 同時辨識大量文件
若要從文件中擷取文字資料,必須先進行辨識。處理大量文件時,同時處理多份文件會很有幫助。在此情況下,可將分析與辨識的工作負載分散到處理器核心上,進而加快處理速度。
  1. 匯出為歸檔格式
辨識後的文件會儲存為適當的格式。最適合用來儲存文件的格式包括 PDF、PDF/A,以及含 MRC 的 PDF 和 PDF/A。儲存為這些格式時,可以使用一種模式,將文字置於文件影像下方,如此即可完整保留文件版面格式,並支援全文檢索。MRC 設定可在不損失視覺品質的情況下大幅縮減檔案大小。此外,儲存為 PDF 格式時,還可自訂文件的安全性設定,以防止未經授權的檢視與列印。

情境實作

本主題提供的程式碼範例僅適用於 Windows。
以下將詳細說明使用 ABBYY FineReader Engine 12 建立用於歸檔的文件數位副本之建議方法。此方法採用最適合此用途的處理設定。在此實作中,文件掃描階段會略過。如需實作掃描的提示,請參閱下方的 特定任務的進一步最佳化
若要開始使用 ABBYY FineReader Engine,您需要建立 Engine 物件。Engine 物件是 ABBYY FineReader Engine 物件階層中的頂層物件,提供各種全域設定、部分處理方法,以及用於建立其他物件的方法。若要建立 Engine 物件,您可以使用 InitializeEngine 函式。另請參閱載入 Engine 物件的其他方式 (Win) 。

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // 請以 FREngine.dll 的完整路徑、您的 Customer Project ID,
        // 以及(如適用)線上授權權杖檔案的路徑和線上授權密碼來初始化這些變數
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // 載入 FREngine.dll 程式庫
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("無法載入 " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("找不到 InitializeEngine 函式");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("找不到 DeinitializeEngine 函式");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("找不到 DllCanUnloadNow 函式");
            }
            // 將指標轉換為委派
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // 呼叫 InitializeEngine 函式,
            // 傳入線上授權檔案的路徑及線上授權密碼
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // 釋放 FREngine.dll 程式庫
            engine = null;
            // 呼叫 FreeLibrary 前先刪除所有物件
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Kernel32.dll 函式
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // FREngine.dll 函式
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine(string customerProjectId, string licensePath, 
        string licensePassword, string tempFolder, string dataFolder, bool isSharedCPUCoresMode, 
        ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // 私有變數
    private FREngine.IEngine engine = null;
    // FREngine.dll 的 Handle
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

// 使用 FREngine.dll 的路徑、您的 FineReader Engine Customer Project ID,
// 以及(如適用)線上授權權杖的路徑與線上授權密碼來初始化這些變數
wchar_t* FreDllPath;
wchar_t* CustomerProjectId;
wchar_t* LicensePath;  // 如果您未使用線上授權,請將這些變數設為空字串
wchar_t* LicensePassword;
// FREngine.dll 的 HANDLE
static HMODULE libraryHandle = 0;
// 全域 FineReader Engine 物件
FREngine::IEnginePtr Engine;
void LoadFREngine()
{
    if( Engine != 0 ) {
    // 已經載入
    return;
    }
    // 第一步:載入 FREngine.dll
    if( libraryHandle == 0 ) {
        libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
        if( libraryHandle == 0 ) {
            throw L"載入 ABBYY FineReader Engine 時發生錯誤";
        }
    }
    // 第二步:取得 Engine 物件
    typedef HRESULT ( STDAPICALLTYPE* InitializeEngineFunc )( BSTR, BSTR, BSTR, BSTR, 
        BSTR, VARIANT_BOOL, FREngine::IEngine** );
    InitializeEngineFunc pInitializeEngine =
    ( InitializeEngineFunc )GetProcAddress( libraryHandle, "InitializeEngine" );
    if( pInitializeEngine == 0 || pInitializeEngine( CustomerProjectId, LicensePath, 
        LicensePassword, L"", L"", VARIANT_FALSE, &Engine ) != S_OK ) {
    UnloadFREngine();
    throw L"載入 ABBYY FineReader Engine 時發生錯誤";
    }
}
ABBYY FineReader Engine 可透過 Engine 物件的 LoadPredefinedProfile 方法,載入最適合此情境的各項處理設定。此方法會接收設定檔名稱作為輸入參數。如需更多資訊,請參閱 Working with ProfilesABBYY FineReader Engine 針對此情境支援 2 種設定:

設定檔名稱

說明

DocumentArchiving_Accuracy

此設定已針對準確度最佳化:

  • 可偵測影像中的最多文字,包括嵌入在影像中的文字。
  • 不執行文件邏輯結構的完整合成。
此設定檔不適用於將文件轉換為 RTF、DOCX 或純文字 PDF。若要進行此類轉換,請使用文件轉換設定檔。

DocumentArchiving_Speed

此設定已針對處理速度最佳化:

  • 可偵測影像中的最多文字,包括嵌入在影像中的文字。
  • 不執行歪斜校正。
  • 不執行文件邏輯結構的完整合成。
  • 加快文件分析與辨識的處理程序。
此設定檔不適用於將文件轉換為 RTF、DOCX 或純文字 PDF。若要進行此類轉換,請使用文件轉換設定檔。

C#

// 載入預先定義的設定檔
engine.LoadPredefinedProfile("DocumentArchiving_Accuracy");

C++ (COM)

// 載入預先定義的設定檔
Engine->LoadPredefinedProfile( L"DocumentArchiving_Accuracy" );
如果您想變更處理設定,請使用適當的參數物件。如需更多資訊,請參閱 特定任務的進一步最佳化
ABBYY FineReader Engine 提供 FRDocument 物件,可用於處理多頁文件。使用此物件可保留文件的邏輯組織結構。若要載入單一文件的影像並進行預處理,您應建立 FRDocument 物件並將影像加入其中。您可以採用下列任一方式:

C#

// 從影像檔建立 FRDocument 物件
FREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );

C++ (COM)

// 從影像檔建立 FRDocument 物件
FREngine::IFRDocumentPtr frDocument = Engine->CreateFRDocumentFromImage( L"C:\\MyImage.tif", 0 );
若要辨識文件,建議使用 FRDocument 物件的分析與辨識方法。此物件提供完整的方法集,可用於文件分析、辨識與合成。若要透過單一方法完成文件分析、辨識與合成,最方便的是使用 Process 方法。此方法也能以最高效率運用多處理器與多核心系統的平行處理功能。不過,您也可以使用 PreprocessAnalyzeRecognizeSynthesize 方法,依序執行預處理、分析、辨識與合成。

C#

// 分析、辨識並合成文件
// 不需要額外參數,因為這些參數已由處理設定檔設定
frDocument.Process( null );

C++ (COM)

// 分析、辨識並合成文件
// 不需要額外參數,因為這些參數已由處理設定檔設定
frDocument->Process( 0 );
若要儲存已辨識的文件,您可以使用 FRDocument 物件的 Export 方法,並將 FileExportFormatEnum 常數作為其中一個參數。在此情況下,例如,您可以使用 MRC,並將匯出模式設為 PEM_ImageOnText (PDFExportParams 物件的 TextExportMode 屬性) ,將文件儲存為 PDF 格式。您可以使用對應的匯出物件來變更預設的匯出參數。如需更多資訊,請參閱下方的 特定任務的進一步最佳化完成 FRDocument 物件的使用後,請釋放此物件所使用的所有資源。請使用 IFRDocument::Close 方法。

C#

// 將已辨識的文件儲存為歸檔格式(例如 PDF)
// 建立 PDFExportParams 物件
FREngine.PDFExportParams exportParams = engine.CreatePDFExportParams();
// 設定所需參數
exportParams.MRCMode = FREngine.PDFMRCModeEnum.MRC_Auto;
exportParams.TextExportMode = FREngine.PDFExportModeEnum.PEM_ImageOnText;
// 匯出時使用這些參數
frDocument.Export( "C:\\MyText.pdf", FREngine.FileExportFormatEnum.FEF_PDF, exportParams );
// 釋放 FRDocument 物件
frDocument.Close();

C++ (COM)

// 將已辨識的文件儲存為歸檔格式(例如 PDF)
// 建立 PDFExportParams 物件
FREngine::IPDFExportParamsPtr params = Engine->CreatePDFExportParams();
// 設定所需參數
params->MRCMode = FREngine::MRC_Auto;
params->TextExportMode = FREngine::PEM_ImageOnText;
// 匯出時使用這些參數
frDocument->Export(L"C:\\MyText.pdf", FREngine::FEF_PDF, params);
// 釋放 FRDocument 物件
frDocument->Close();
使用完 ABBYY FineReader Engine 後,您需要卸載 Engine 物件。為此,請使用匯出的 DeinitializeEngine 函式。

C#

public class EngineLoader : IDisposable
{
    // 卸載 FineReader Engine
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine 尚未載入
            return;
        }
        engine = null;
        // 在呼叫 FreeLibrary 前刪除所有物件
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        int hresult = deinitializeEngine();
 
        hresult = dllCanUnloadNow();
        if (hresult == 0)
        {
            FreeLibrary(dllHandle);
        }
        dllHandle = IntPtr.Zero;
        initializeEngine = null;
        deinitializeEngine = null;
        dllCanUnloadNow = null;
        // 清理完成後擲回例外狀況
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Kernel32.dll 函式
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // FREngine.dll 函式
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine( string customerProjectId, string LicensePath, string LicensePassword, , , , ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // 私有變數
    private FREngine.IEngine engine = null;
    // FREngine.dll 的 Handle
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

void UnloadFREngine()
{
 if( libraryHandle == 0 ) {
  return;
 }
 // 釋放 Engine 物件
 Engine = 0;
 // 解除初始化 FineReader Engine
 typedef HRESULT ( STDAPICALLTYPE* DeinitializeEngineFunc )();
 DeinitializeEngineFunc pDeinitializeEngine =
  ( DeinitializeEngineFunc )GetProcAddress( libraryHandle, "DeinitializeEngine" );
 if( pDeinitializeEngine == 0 || pDeinitializeEngine() != S_OK ) {
  throw L"卸載 ABBYY FineReader Engine 時發生錯誤";
 }
 // 現在可以安全地釋放 FREngine.dll 程式庫
 FreeLibrary( libraryHandle );
 libraryHandle = 0;
}

必要資源

您可以使用 FREngineDistribution.csv 檔案,自動建立應用程式正常運作所需的檔案清單。若要依此情境進行處理,請在第 5 欄 (RequiredByModule) 中選取下列值: Core Core.Resources Opening Opening, Processing Processing Processing.OCR Processing.OCR, Processing.ICR Processing.OCR.NaturalLanguages Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages Export Export, Processing Export.Pdf Export.Pdf, Opening.Pdf 如果您修改了標準情境,請據此調整所需模組。您還需要指定介面語言、辨識語言,以及應用程式使用的任何其他功能 (例如,若您需要開啟 PDF 檔案,請指定 Opening.PDF;若您需要辨識 CJK 語言 的文字,請指定 Processing.OCR.CJK) 。如需進一步資訊,請參閱 Working with the FREngineDistribution.csv File

特定任務的進一步最佳化

以下概述了說明主題,其中包含有關在文件處理不同階段自訂設定的其他資訊:
  • 掃描 - 僅限 Windows
    • 掃描
      ABBYY FineReader Engine 文件掃描情境的說明。
  • 識別
  • 識別手寫文字
    DocumentArchiving_*** 設定檔不包含手寫或工整手寫文字的識別功能。如果您需要識別手寫文字,請將 PageAnalysisParams 物件的 DetectHandwritten 屬性設為 TRUE。
  • PageProcessingParams 物件
    此物件可讓您自訂分析與辨識參數。使用此物件,您可以指定必須偵測的影像與文字特性 (反相影像、影像方向、條碼、辨識語言、辨識誤差範圍) 。
  • SynthesisParamsForPage 物件
    此物件包含負責在合成過程中還原頁面格式的參數。
  • SynthesisParamsForDocument 物件
    此物件可自訂文件合成的方式,以還原其結構與格式。
  • MultiProcessingParams 物件 - 支援 Linux 和 Windows
    處理大量影像時,同時處理會很有幫助。在這種情況下,處理負載會在影像開啟與預處理、版面分析、辨識及匯出期間分散到各個處理器核心,因此可加快處理速度。
    讀取模式 (同時或循序) 可使用 MultiProcessingMode 屬性設定,而 RecognitionProcessesCount 屬性則用來控制可啟動的處理程序數量。
  • 匯出
    • 調整匯出參數
      使用匯出參數物件自訂文件匯出。
    • PDFExportParams 物件
      此物件只需幾個參數即可讓您調整 PDF (PDF/A) 匯出設定。
    • 若要自訂 PDF (PDF/A) 格式的匯出模式,請使用 PDFExportParams 物件的 TextExportMode 屬性;若要自訂 MRC 設定,請使用 MRCMode 屬性。
    • 此外,您也可以自訂影像匯出設定,以加快處理速度、進一步縮小檔案大小等。例如,若符合您的使用情境,您可以將彩色影像儲存為灰階或黑白影像 (請使用 PDFExportParams 物件的 Colority 屬性) 。
    • 您可以變更影像解析度,讓產生的電子副本之後可在印表機上列印或在電腦螢幕上檢視;或者,您也可以選擇僅適合閱讀文字、圖形品質較差的低解析度 (請使用 PDFExportParams 物件的 ResolutionResolutionType 屬性) 。
  • 分割為多個文件
    • 在這種情況下,可能需要將一批影像分割成多個文件。ABBYY FineReader Engine 12 不支援自動文件分割。不過,您可以使用 ABBYY FlexiCapture Engine 來實作自動分割。例如,可根據文件的頁數,或根據帶有分隔條碼的頁面來分割文件。實作條碼分割時,您可以使用僅從文件擷取條碼值的情境

另請參閱

基本使用案例實作