메인 콘텐츠로 건너뛰기
이 시나리오는 종이 문서를 처리하여 디지털 아카이브에 저장할 때 사용되며, 특히 계약서, 프로젝트 문서, 청구서, 증명서 등의 아카이브를 구축할 때 유용합니다. 이 처리 시나리오에서는 종이 문서를, 문서의 모든 정보가 검색 가능한 형식으로 포함된 편집 불가능한 디지털 사본으로 변환합니다. 이렇게 처리하면 전자 아카이브에서 전문 검색을 사용해 문서의 디지털 사본을 쉽게 찾을 수 있고, 문서의 텍스트 일부를 복사할 수 있으며, 문서를 이메일로 보내거나 인쇄할 수도 있습니다. 디지털 사본을 만들려면 먼저 문서가 여러 처리 단계를 거쳐야 하며, 각 단계마다 고유한 특성이 있습니다.
  1. 스캔 이미지 전처리
스캔 이미지는 인식 전에 일부 전처리가 필요할 수 있습니다. 예를 들어, 스캔한 문서에 배경 잡음, 기울어진 텍스트, 반전된 색상, 검은 여백, 잘못된 방향 또는 부적절한 해상도 등의 문제가 있을 수 있습니다.
  1. 대량 문서의 동시 인식
문서에서 텍스트 데이터를 추출하려면 먼저 문서를 인식해야 합니다. 많은 양의 문서를 처리할 때는 문서를 동시에 처리하는 방식이 유용할 수 있습니다. 이 경우 분석 및 인식 작업 부하를 프로세서 코어에 분산할 수 있으므로 처리 속도를 높일 수 있습니다.
  1. 아카이브 형식으로 내보내기
인식된 문서는 적절한 저장 형식으로 저장됩니다. 문서를 저장하는 데 가장 적합한 형식은 PDF, PDF/A, PDF, PDF/A with MRC입니다. 이러한 형식으로 저장할 때는 텍스트를 문서 이미지 아래에 배치하는 모드를 사용할 수 있습니다. 이렇게 하면 문서 서식을 완전히 유지하면서 전문 검색도 가능해집니다. MRC 설정을 사용하면 시각적 품질 손실 없이 파일 크기를 크게 줄일 수 있습니다. 또한 PDF 형식으로 저장할 때는 무단 열람 및 인쇄로부터 문서를 보호하도록 보안 설정을 사용자 지정할 수 있습니다.

시나리오 구현

이 항목에 제공된 코드 샘플은 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 로드 중 오류 발생";
    }
}
ABBYY FineReader Engine에서는 Engine 객체의 LoadPredefinedProfile 메서드를 사용하여 이 시나리오에 가장 적합한 처리 설정을 모두 로드할 수 있습니다. 이 메서드는 입력 파라미터로 프로필 이름을 받습니다. 자세한 내용은 프로필 작업을 참조하세요.ABBYY 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" );
처리 설정을 변경하려면 적절한 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 );
문서를 인식하려면 FRDocument 객체의 분석 및 인식 메서드를 사용하는 것이 좋습니다. 이 객체는 문서 분석, 인식 및 합성을 위한 다양한 메서드를 제공합니다. 하나의 메서드만으로 문서 분석, 인식 및 합성을 수행할 수 있는 가장 편리한 메서드는 Process 메서드입니다. 또한 이 메서드는 다중 프로세서 및 멀티코어 시스템의 동시 처리 기능을 가장 효율적으로 활용합니다. 하지만 Preprocess, Analyze, Recognize, Synthesize 메서드를 사용하여 전처리, 분석, 인식 및 합성을 순차적으로 수행할 수도 있습니다.

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 객체를 언로드해야 합니다. 이렇게 하려면 export된 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에 대한 핸들
    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 languages의 텍스트를 인식해야 하는 경우 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 속성은 시작할 수 있는 프로세스 수를 제어합니다.
  • 내보내기
    • 내보내기 Parameter 조정
      내보내기 매개변수 객체를 사용해 문서 내보내기를 사용자 지정합니다.
    • PDFExportParams 객체
      이 객체를 사용하면 몇 가지 매개변수만으로 PDF(PDF/A) 내보내기를 조정할 수 있습니다.
    • PDF(PDF/A) 형식의 내보내기 모드를 사용자 지정하려면 PDFExportParams 객체의 TextExportMode 속성을 사용하고, MRC 설정을 사용자 지정하려면 MRCMode 속성을 사용합니다.
    • 또한 처리 속도를 높이거나 파일 크기를 추가로 줄이기 위해 이미지 내보내기 설정을 사용자 지정할 수 있습니다. 예를 들어, 사용 시나리오에 맞는 경우 컬러 이미지를 회색조 또는 흑백 이미지로 저장할 수 있습니다(PDFExportParams 객체의 Colority 속성 사용).
    • 이후 생성된 전자 사본을 프린터로 인쇄하거나 컴퓨터 화면에서 볼 수 있도록 이미지 해상도를 변경할 수 있으며, 텍스트 판독만 가능하고 그래픽 품질은 매우 낮은 저해상도를 선택할 수도 있습니다(PDFExportParams 객체의 ResolutionResolutionType 속성 사용).
  • 문서 단위로 분리
    • 이 시나리오에서는 이미지 배치를 여러 문서로 분리해야 할 수 있습니다. ABBYY FineReader Engine 12는 자동 문서 분리를 지원하지 않습니다. 하지만 ABBYY FlexiCapture Engine을 사용하면 자동 분리를 구현할 수 있습니다. 예를 들어 문서의 페이지 수를 기준으로 하거나, 구분용 바코드가 있는 페이지를 기준으로 문서를 분리할 수 있습니다. 바코드 분리를 구현할 때는 문서에서 바코드 값만 추출하는 시나리오를 사용할 수 있습니다.

참고 항목

기본 사용 시나리오 구현