跳轉到主要內容
在此情境中,ABBYY FineReader Engine 用於讀取條碼。例如,為了自動分隔文件、供文件管理系統處理,或為文件建立索引與分類,可能都需要讀取條碼。 此情境也可作為其他情境的一部分使用。例如,以高速生產型掃描器掃描的文件可藉由條碼進行分隔,或是為長期保存而準備的文件,可根據其條碼值存入歸檔文件管理系統中。 從文字中擷取條碼時,系統可偵測所有條碼,也可僅偵測特定類型且具有特定值的條碼。系統可以取得條碼值並計算其校驗碼。若要以最快速度和最佳品質取得條碼辨識結果:
  1. 使用最佳解析度為 300 dpi 的彩色圖片。
  2. 使用設定檔調整辨識速度 (詳見 使用設定檔) 。
辨識出的條碼值可儲存為最便於後續處理的格式,例如 TXT。

情境實作

本主題中提供的程式碼範例僅適用於 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 物件
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 時發生錯誤";
    }
}
您可以使用 Engine 物件的 LoadPredefinedProfile 方法,選取最適合的設定。此方法會接受所用設定檔的名稱作為輸入參數。如需設定檔的詳細資訊,請參閱 使用設定檔ABBYY FineReader Engine 支援此情境的 2 種設定:
Profile nameDescription
BarcodeRecognition_Accuracy僅擷取條碼 (不會偵測文字、圖片或表格) 。此設定已針對準確度最佳化。 <Warning> 此設定檔需要授權中包含 Barcode Autolocation 模組。 </Warning>
BarcodeRecognition_Speed僅擷取條碼 (不會偵測文字、圖片或表格) 。此設定已針對處理速度最佳化。 <Warning> 此設定檔需要授權中包含 Barcode Autolocation 模組。 </Warning>

C#

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

C++ (COM)

// 載入預先定義的設定檔
Engine->LoadPredefinedProfile( L"BarcodeRecognition_Speed" );
如果您想變更處理所使用的設定,請使用對應的參數物件。如需更多資訊,請參閱下方的 其他最佳化 一節。
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 );
如果已載入 BarcodeRecognition 設定檔,您可以使用 FRDocument 物件的 Process 方法只擷取條碼。在此情況下,ABBYY FineReader Engine 只會偵測含有條碼的區塊,不會偵測其他區塊。您可以透過 Layout 物件存取已辨識的條碼區塊;它是 FRPage 物件的子物件,而 FRPage 物件代表文件中的一個頁面。若要讀取特定類型的條碼,請指定 BarcodeParams 物件中的適當參數,並將 BarcodeParams 物件作為上述其中一個函式的參數傳入。

C#

// 當已載入 BarcodeRecognition 設定檔時,
// 如果條碼符合規格,
// 您不需要將任何其他參數傳遞給處理方法
frDocument.Process( null );
// 如果您需要讀取特定類型的條碼
// 建立一個 DocumentProcessingParams 物件
FREngine.IDocumentProcessingParams dpp = engine.CreateDocumentProcessingParams();
// 指定必要參數
dpp.PageProcessingParams.PageAnalysisParams.BarcodeParams.Type = ( int )FREngine.BarcodeTypeEnum.BT_Code39;
// 現在使用這些參數辨識條碼
frDocument.Process( dpp );

C++ (COM)

// 當已載入 BarcodeRecognition 設定檔時,
// 如果條碼符合規格,
// 您不需要將任何其他參數傳遞給處理方法
frDocument->Process( 0 );
// 如果您需要讀取特定類型的條碼
// 建立一個 DocumentProcessingParams 物件
FREngine::IDocumentProcessingParamsPtr params = Engine->CreateDocumentProcessingParams();
// 指定必要參數
params->PageProcessingParams->PageAnalysisParams->BarcodeParams->Type = FREngine::BT_Code39;
// 現在使用這些參數辨識條碼
frDocument->Process( params );
若要將已辨識條碼的值儲存到檔案中,您可以使用 FRDocument 物件的 Export 方法,並將 FileExportFormatEnum 常數指定為其中一個參數。例如,在此情境中可匯出為 TXT。您也可以使用對應的匯出物件來變更匯出的預設參數。進一步資訊請參閱下方的 針對特定任務的其他最佳化完成 FRDocument 物件的作業後,請釋放此物件所使用的所有資源。請使用 IFRDocument::Close 方法。

C#

// 將已辨識的條碼儲存為某種格式(例如 TXT)
frDocument.Export( "C:\\barcodes.txt", FREngine.FileExportFormatEnum.FEF_TextUnicodeDefaults, null );
// 釋放 FRDocument 物件
frDocument.Close();

C++ (COM)

// 將已辨識的條碼儲存為某種格式(例如 TXT)
frDocument->Export( L"C:\\barcodes.txt", FREngine::FEF_TextUnicodeDefaults, 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

其他最佳化

以下是說明檔中可供您參考的章節,您可以在其中找到關於為各個處理階段設定參數的其他資訊:
  • 擷取並讀取條碼
    • BarcodeParams Object
      此物件可讓您設定條碼分析與讀取參數。
    • Recognizing Barcodes
      說明條碼辨識中的特殊情況,並提供使用條碼時的實用提示。
    • Barcode Types
      ABBYY FineReader Engine 12 所支援的條碼清單及其簡要說明。
    • FRDocument 物件
      除了條碼值之外,您可能還需要擷取文件中包含的其他資訊。在這種情況下,您可能會想使用 FRDocument 物件的方法。
    • PageProcessingParams Object
      此物件可讓您為整份文件設定分析與辨識參數。使用此物件時,您可以指定是否要辨識條碼值。條碼讀取參數可透過 PageAnalysisParams 子物件的 BarcodeParams 和 DetectBarcodes Properties 存取。
    • Working with Layout and Blocks
      您也可以手動標記條碼區塊,並指定其分析與讀取參數。本節提供有關區塊操作的詳細資訊。
  • 使用已辨識的條碼值
    • BarcodeBlock Object
      此物件的 Text 和 BarcodeText Properties 包含透過辨識取得的條碼值。此物件的其他 Properties 可用來取得條碼類型、方向及其他參數。
  • 匯出

另請參見

基本使用情境實作