메인 콘텐츠로 건너뛰기
많은 국가의 공식 여행 문서 또는 신분증에는 문서 데이터를 더욱 정확하게 처리할 수 있도록 기계 판독 영역(MRZ)이 포함되어 있습니다. MRZ는 ICAO Document 9303에 따라 작성된 OCR-B 글꼴 텍스트 2줄 또는 3줄로 구성됩니다(자세한 사양은 ICAO 웹사이트 참조). 이 시나리오는 고객 온보딩 또는 신원 확인 프로세스에서 신분증의 기계 판독 영역으로부터 데이터를 추출하는 데 사용됩니다. 시스템은 문서 이미지에서 MRZ를 인식하고 그 안의 데이터를 추출합니다. 추출된 데이터에는 문서와 소지자에 대한 개인정보가 포함된 여러 field가 들어 있습니다(문서 유형, 만료일, 문서 소지자의 이름과 성 등). fields를 검색하고, 데이터를 검증한 다음, 후속 처리를 위해 외부 파일에 저장할 수 있습니다. MRZ에서 데이터를 추출하기 위해 일반적으로 스캔하거나 전자 형식으로 저장한 이미지 파일은 여러 처리 단계를 거치며, 각 단계마다 고유한 특성이 있습니다:
  1. 스캔한 이미지 또는 사진 전처리
MRZ가 있는 신분증의 인적사항 페이지를 스캔하거나 사진으로 촬영합니다. 모바일 장치의 디지털 카메라로 촬영한 사진은 해상도와 품질이 낮을 수 있습니다. 또한 이미지는 인식 전에 일부 전처리가 필요할 수 있습니다.
  1. MRZ에서 데이터 추출
각 이미지에서는 MRZ를 하나만 캡처할 수 있습니다. 2줄 또는 3줄 각각의 텍스트를 인식하고 파싱하여 데이터 field를 추출합니다. 일부 field와 MRZ 전체에는 체크섬이 있어 데이터 검증에 도움이 됩니다.
  1. 외부 파일로 내보내기
추출된 데이터를 외부 형식으로 저장할 수도 있습니다. XML 및 JSON이 지원됩니다. 아래에 설명된 절차는 Linux 및 Windows용 MRZExtraction 코드 샘플에 구현되어 있습니다.

시나리오 구현

이 항목에 제공된 코드 샘플은 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,
        // 그리고 필요한 경우 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("Can't load " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find InitializeEngine function");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DeinitializeEngine function");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DllCanUnloadNow function");
            }
            // 포인터를 대리자로 변환합니다
            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 핸들
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
이 시나리오에 적합한 처리 설정은 Engine 객체의 LoadPredefinedProfile 메서드를 사용해 불러올 수 있습니다. 이 메서드는 설정 프로필 이름을 입력 Parameter로 사용합니다. 자세한 내용은 프로필 사용를 참조하세요.이 시나리오에 대한 설정은 MachineReadableZone 사전 정의 프로필에서 사용할 수 있습니다:
  • 이미지의 모든 텍스트를 감지하고 추출할 수 있습니다(그림, 벡터 그래픽, 표는 감지되지 않음).
  • 해상도 및 기하학적 보정이 자동으로 수행됩니다.

C#

// 사전 정의 프로필 불러오기
engine.LoadPredefinedProfile("MachineReadableZone");
처리 설정을 변경하려면 적절한 Parameter 객체를 사용하세요. 자세한 내용은 아래의 Additional optimization for specific tasks를 참조하세요.MRZ 캡처는 ABBYY FineReader Engine 라이선스가 MRZCapture 모듈을 지원하는 경우에만 가능합니다.
FineReader Engine에 이미지를 불러오려면 다음 객체의 메서드를 사용할 수 있습니다:
Linux 및 Windows 사용자는 Parallel Processing with ABBYY FineReader Engine에서 각 접근 방식의 장단점을 확인할 수 있습니다. 이 항목에서는 FRDocument에 중점을 둡니다.
FRDocument 객체에 이미지를 불러오려면 다음 중 하나를 수행하세요:이 모든 메서드는 입력 Parameter로 PrepareImageMode 객체를 받으며, 이를 통해 이미지 전처리의 다양한 매개변수를 지정할 수 있습니다. IEngine::CreatePrepareImageMode 메서드를 호출해 이 객체를 만든 다음, 필요에 따라 해당 속성을 변경하고 이미지 열기 메서드에 전달하세요.

C#

// 문서 생성
FREngine.IFRDocument frDoc = engine.CreateFRDocument();
// 문서에 이미지 파일 추가
document.AddImageFile( imagePath, null, null );
MRZ에서 데이터를 추출하려면 다음 단계를 따르세요.
  1. [선택 사항] Engine 객체의 CreateMrzProcessingParams 메서드를 사용하여 MrzProcessingParams 객체를 생성합니다. 그런 다음 필요한 값으로 해당 속성을 설정합니다.
  2. FRPage 객체의 ExtractMrz 메서드를 호출하면서, 이전 단계에서 구성한 MrzProcessingParams 객체를 입력 Parameter로 전달합니다. 기본 MRZ 캡처 설정을 사용하려면 NULL만 전달하면 됩니다. 그러면 캡처된 MRZ에서 구문 분석한 정보가 포함된 MrzData 객체가 반환됩니다.

C#

// MRZ 추출
FREngine.IFRPage page = document.Pages.Item(0);
FREngine.IMrzData mrzData = page.ExtractMrz( null );
MrzData 객체에는 MRZ에서 추출한 모든 데이터가 들어 있습니다. GetLine 메서드를 사용해 기계 판독 텍스트의 각 줄에 액세스할 수 있으며, GetFieldGetFieldByType 메서드를 사용해 field를 순회할 수 있습니다. 다음 유형의 field가 추출됩니다.
  • 문서 유형
  • 문서 하위 유형
  • 발행 국가
  • 이름
  • 문서 번호
  • 국적
  • 생년월일
  • 성별
  • 만료일
  • 개인 번호
  • 추가 데이터 줄 1
  • 추가 데이터 줄 2
MrzField 객체는 추출된 field에 대한 전체 정보를 제공합니다. field 값을 가져오려면 Text 속성을 사용하고, 이미지에서 field의 위치를 가져오려면 Region 속성을 사용합니다. 데이터를 검증하려면 MrzDataMrzField 객체의 Checksum, HasChecksum, IsChecksumVerified 속성을 통해 제공되는 체크섬을 사용합니다. 모든 field 유형이 체크섬을 지원하는 것은 아니므로, 체크섬을 가져오기 전에 값을 확인할 수 있도록 HasChecksum 속성이 제공됩니다.MrzField 객체의 InsertRemove 메서드를 사용하면 field의 인식된 텍스트를 수동으로 편집할 수 있습니다.

C#

// 문서 번호의 체크섬 검증
FREngine.IMrzField documentNumberField = mrzData.GetFieldByType(FREngine.MrzFieldTypeEnum.MFT_DocumentNumber);
bool isNumberVerified = documentNumberField.IsChecksumVerified;
추출된 데이터는 XML 또는 JSON 파일에 저장할 수 있습니다. 기본 매개변수로 데이터를 내보내려면 MrzData 객체의 ExportToFile 메서드를 호출하고 파일 경로를 입력 매개변수로 전달합니다. 사용자 지정 매개변수로 데이터를 내보내려면 MrzData 객체의 ExportToFileEx 메서드를 호출하고 MrzJsonExportParams 객체 또는 MrzXmlExportParams 객체에 대한 포인터를 입력 매개변수로 전달합니다.C#
// XML 형식으로 저장
mrzData.ExportToFile("C:\\ExtractedData.xml", FREngine.MrzExportFormatEnum.MEF_Xml);
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 핸들
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

필수 리소스

애플리케이션이 작동하는 데 필요한 파일 목록을 자동으로 생성하려면 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)도 지정해야 합니다. 자세한 내용은 FREngineDistribution.csv 파일 작업을 참조하십시오.

추가 최적화

다음은 다양한 처리 단계의 매개변수 설정에 대한 추가 정보를 찾을 수 있는 도움말 파일의 섹션입니다.

참고 항목

기본 사용 시나리오 구현