跳轉到主要內容
此情境的結果是取得文件的可編輯版本。 在此情境中,系統會辨識文件影像,完整保留原始格式,並將資料儲存為可編輯的檔案格式。因此,您可取得文件的可編輯版本,方便檢查錯誤並進行修改。您也可以複製全部或部分文字,以便重複使用。 文件會經過數個處理步驟,這些步驟在某些方面與其他常見情境略有不同:
  1. 掃描影像或照片的預處理
透過掃描器或數位相機取得的影像,在進行光學辨識之前可能需要先做一些調整。例如,帶有雜訊的影像或文字行扭曲的影像,必須先加以校正,才能成功完成光學辨識。
  1. 在完整還原文件結構與格式的情況下進行辨識
辨識文件時,系統會識別文件中的各種版面元素 (文字、表格、影像、分隔符號等) 。在文件合成過程中,系統會還原文件的邏輯結構,而頁面合成則可完整還原文件格式 (字型、樣式等) 。
  1. 匯出為可編輯格式
辨識後的文件會儲存為可編輯格式,例如 RTF、DOCX。

情境實作

本主題中提供的程式碼範例僅適用於 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 的控制代碼
    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,
// 以及(如適用)Online License 權杖和 Online License 密碼的路徑填入這些變數
wchar_t* FreDllPath;
wchar_t* CustomerProjectId;
wchar_t* LicensePath;  // 若不使用 Online License,請將這些變數設為空字串
wchar_t* LicensePassword;
// FREngine.dll 的 HANDLE
static HMODULE libraryHandle = 0;
// 全域 FineReader Engine object
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 object
    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 種設定:

設定檔名稱

說明

DocumentConversion_Accuracy

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

  • 最佳品質。啟用字型樣式偵測,以及文件邏輯結構的完整重建。

DocumentConversion_Normal

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

  • 最佳品質。啟用字型樣式偵測,以及文件邏輯結構的完整重建。
  • 不會校正影像方向。
  • 加快文件分析程序。

C#

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

C++ (COM)

// 載入預先定義的設定檔
Engine->LoadPredefinedProfile( L"DocumentConversion_Normal" );
如果您想變更處理設定,請使用適當的參數物件。更多資訊請參閱下方的 特定任務的其他最佳化
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 );
使用已載入的 DocumentConversion_Normal 設定檔進行影像預處理時,不包含方向偵測。如果您希望自動偵測影像方向,則需要設定其他參數,並將對應物件傳遞至預處理函式。更多資訊請參閱下方的 特定任務的其他最佳化
若要辨識文件,我們建議您使用 FRDocument 物件的分析與辨識方法。此物件提供一系列用於文件分析、辨識與合成的方法。最方便的是 Process 方法,可一次完成文件分析、辨識與合成。它也能以最高效率運用多處理器與多核心系統的平行處理能力。不過,您也可以使用 PreprocessAnalyzeRecognizeSynthesize 方法,依序執行預處理、分析、辨識與合成。

C#

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

C++ (COM)

// 分析、辨識並合成文件
// 不需要額外參數,因為這些參數已由處理設定檔設定
frDocument->Process( 0 );
若要儲存已辨識的文件,您可以使用 FRDocument 物件的 Export 方法,並將 FileExportFormatEnum 常數作為其中一個參數傳入。您可以使用對應的匯出物件來變更匯出的預設參數。請參閱下方的 特定工作的其他最佳化設定 以取得更多資訊。完成 FRDocument 物件的作業後,請釋放此物件使用的所有資源。請使用 IFRDocument::Close 方法。

C#

// 以可編輯格式儲存已辨識的文件(例如 RTF)
frDocument.Export( "C:\\MyText.rtf", FREngine.FileExportFormatEnum.FEF_RTF, null );
// 釋放 FRDocument 物件
frDocument.Close();

C++ (COM)

// 以可編輯格式儲存已辨識的文件(例如 RTF)
frDocument->Export( L"C:\\MyText.rtf", FREngine::FEF_RTF, 0 );
// 釋放 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 的控制代碼
    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 如果您修改了標準情境,請相應調整所需模組。您還需要指定介面語言、辨識語言,以及應用程式使用的任何其他功能 (例如,若您需要開啟 PDF 檔案,請指定 Opening.PDF;若您需要辨識 CJK languages 的文字,請指定 Processing.OCR.CJK) 。如需更多詳細資訊,請參閱 Working with the FREngineDistribution.csv File

針對特定任務的其他最佳化

以下概述了 Help 主題,其中包含在將文件轉換為可編輯格式的各個階段自訂設定的補充資訊:
  • 掃描 - 僅限 Windows
    • 掃描
      說明 ABBYY FineReader Engine 的文件掃描情境。
  • 辨識
    • 微調預處理、分析、辨識和合成的參數
      使用分析、辨識和合成參數物件來自訂文件處理。
    • 辨識手寫文字
      DocumentConversion_*** 設定檔不包含手寫或工整書寫文字辨識。如果您需要辨識手寫文字,請將 PageAnalysisParams 物件的 DetectHandwritten 屬性設為 TRUE。
    • PageProcessingParams 物件
      此物件可讓您自訂分析和辨識參數。使用此物件,您可以指定必須偵測的影像和文字特徵 (反相影像、方向、條碼、辨識語言、辨識錯誤容差) 。
    • SynthesisParamsForPage 物件
      此物件包含在合成期間負責還原頁面格式的參數。
    • SynthesisParamsForDocument 物件
      此物件可讓您自訂文件合成:還原其結構和格式。
    • MultiProcessingParams 物件 - 已針對 Linux 和 Windows 實作
      處理大量影像時,同時處理會很有幫助。在此情況下,處理負載會在影像開啟與預處理、版面分析、辨識和匯出期間分散到各個處理器核心上,從而提升處理速度。
      處理模式 (同時或連續) 可使用 MultiProcessingMode 屬性設定。RecognitionProcessesCount 屬性可控制可啟動的處理程序數目。
  • 匯出

另請參閱

基本使用情境實作