메인 콘텐츠로 건너뛰기
이 시나리오에서는 ABBYY FineReader Engine을 사용해 바코드를 읽습니다. 예를 들어 자동 문서 분리, Document Management System을 통한 문서 처리, 또는 문서의 색인 생성 및 분류를 위해 바코드를 읽어야 할 수 있습니다. 이 시나리오는 다른 시나리오의 일부로도 사용할 수 있습니다. 예를 들어, 고속 생산용 스캐너로 스캔한 문서는 바코드를 사용해 분리할 수 있으며, 장기 보관용으로 준비된 문서는 바코드 값을 기준으로 아카이빙 Document Management System에 저장할 수 있습니다. 텍스트에서 바코드를 추출할 때 시스템은 모든 바코드를 감지하거나, 특정 값이 있는 특정 유형의 바코드만 감지할 수 있습니다. 또한 시스템은 바코드 값을 가져오고 체크섬을 계산할 수 있습니다. 바코드를 가장 빠르고 정확하게 인식하려면 다음 사항을 따르십시오.
  1. 최적 해상도인 300 dpi의 컬러 이미지를 사용합니다.
  2. 프로필을 사용해 인식 속도를 조정합니다(자세한 내용은 프로필 작업을 참조).
인식된 바코드 값은 후속 처리에 가장 적합한 형식으로 저장할 수 있으며, 예를 들어 TXT 형식으로 저장할 수 있습니다.

시나리오 구현

이 항목에서 제공되는 코드 샘플은 Windows 전용입니다.
아래에서는 이 시나리오에서 ABBYY FineReader Engine 12를 사용하는 권장 방법을 자세히 설명합니다. 이 권장 방법은 이 시나리오에 가장 적합하다고 판단되는 처리 설정을 사용합니다.
ABBYY FineReader Engine 작업을 시작하려면 Engine 객체를 생성해야 합니다. Engine 객체는 ABBYY FineReader Engine 객체 계층 구조의 최상위 객체로, 다양한 전역 설정과 일부 처리 메서드, 그리고 다른 객체를 생성하는 메서드를 제공합니다.엔진 객체를 생성하려면 InitializeEngine 함수를 사용하십시오. 엔진 객체를 로드하는 다른 방법(Win)도 참조하십시오.

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // FREngine.dll의 전체 경로, Customer Project ID,
        // 그리고 해당하는 경우 Online License 토큰 파일 경로 및 Online License 비밀번호로 이 변수들을 초기화하세요
        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 함수 호출
            // Online License 파일 경로 및 Online License 비밀번호 전달
            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 변수
    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,
// 그리고 해당하는 경우 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;
    }
    // 1단계: FREngine.dll 로드
    if( libraryHandle == 0 ) {
        libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
        if( libraryHandle == 0 ) {
            throw L"ABBYY FineReader Engine 로드 중 오류 발생";
        }
    }
    // 2단계: 엔진 객체 가져오기
    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가지 설정 옵션을 지원합니다:
프로필 이름설명
BarcodeRecognition_Accuracy바코드만 추출합니다(텍스트, 그림, 표는 감지되지 않음). 이 설정은 정확도를 높이도록 최적화되어 있습니다. <Warning> 이 프로필을 사용하려면 라이선스에 Barcode Autolocation 모듈이 포함되어 있어야 합니다. </Warning>
BarcodeRecognition_Speed바코드만 추출합니다(텍스트, 그림, 표는 감지되지 않음). 이 설정은 처리 속도를 높이도록 최적화되어 있습니다. <Warning> 이 프로필을 사용하려면 라이선스에 Barcode Autolocation 모듈이 포함되어 있어야 합니다. </Warning>

C#

// 미리 정의된 프로필 로드
engine.LoadPredefinedProfile("BarcodeRecognition_Speed");

C++ (COM)

// 미리 정의된 프로필 로드
Engine->LoadPredefinedProfile( L"BarcodeRecognition_Speed" );
처리에 사용할 설정을 변경하려면 해당 Parameter 객체를 사용하세요. 자세한 내용은 아래의 추가 최적화 섹션을 참조하세요.
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은 바코드가 포함된 블록만 감지하며, 다른 블록은 감지하지 않습니다. 인식된 바코드 블록은 문서의 페이지를 나타내는 FRPage 객체의 하위 객체인 Layout 객체를 통해 액세스할 수 있습니다.특정 유형의 바코드를 읽으려면 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;
        // 정리 후 예외 throw
        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 변수
    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 표준 시나리오를 수정하는 경우 그에 맞게 필수 모듈도 변경하십시오. 또한 인터페이스 언어, 인식 언어 및 애플리케이션에서 사용하는 추가 기능도 지정해야 합니다(예: PDF 파일을 열어야 하는 경우 Opening.PDF, CJK languages의 텍스트를 인식해야 하는 경우 Processing.OCR.CJK). 자세한 내용은 Working with the FREngineDistribution.csv File을 참조하십시오.

추가 최적화

다음은 여러 처리 단계의 매개변수 설정에 관한 추가 정보를 확인할 수 있는 도움말 파일의 섹션입니다:
  • 바코드 추출 및 읽기
    • BarcodeParams 객체
      이 객체를 사용하면 바코드 분석 및 읽기 매개변수를 설정할 수 있습니다.
    • 바코드 인식
      바코드 인식의 특수한 경우를 설명하고 바코드 작업에 유용한 팁을 제공합니다.
    • 바코드 유형
      ABBYY FineReader Engine 12에서 지원하는 바코드 목록과 각 바코드에 대한 간단한 설명입니다.
    • FRDocument 객체
      바코드 값 외에 문서에 포함된 다른 정보도 추출해야 할 수 있습니다. 이 경우 FRDocument 객체의 메서드를 사용할 수 있습니다.
    • PageProcessingParams 객체
      이 객체를 사용하면 전체 문서에 대한 분석 및 인식 매개변수를 설정할 수 있습니다. 또한 바코드 값을 인식할지 여부도 지정할 수 있습니다. 바코드 읽기 매개변수는 PageAnalysisParams 하위 객체의 BarcodeParams 및 DetectBarcodes 속성을 통해 사용할 수 있습니다.
    • Layout 및 블록 작업
      바코드 블록을 수동으로 표시하고 해당 분석 및 읽기 매개변수를 지정할 수도 있습니다. 이 섹션에서는 블록 작업에 대한 자세한 정보를 제공합니다.
  • 인식된 바코드 값 작업
    • BarcodeBlock 객체
      이 객체의 Text 및 BarcodeText 속성에는 인식을 통해 얻은 바코드 값이 포함됩니다. 이 객체의 다른 속성은 바코드 유형, 방향 및 기타 매개변수를 가져오는 데 사용할 수 있습니다.
  • 내보내기

참고 항목

기본 사용 시나리오 구현