Dynamsoft C++ OCR SDK를 이용한 여권 MRZ 인식
Dynamsoft OCR SDK 정보
전제 조건
윈도우
리눅스
sudo apt install libopencv-dev cmake
C++에서 여권 MRZ 인식
다음 단락에서는 먼저 Dynamsoft OCR SDK를 사용하여 여권의 기계 판독 가능 영역을 현지화하고 해당 텍스트 문자열을 인식한 다음 여권 소책자의 표준 형식에 따라 텍스트 문자열에서 모든 정보를 추출합니다.
CMake 프로젝트 설정
Windows 및 Linux용 CMake 프로젝트를 만들고 디버그하려면 Visual Studio Code에 CMake 확장을 설치하는 것이 좋습니다.
CMakeLists에서 Dynamsoft OCR 및 OpenCV의 헤더 파일과 연결 라이브러리를 구성해 보겠습니다.
cmake_minimum_required (VERSION 2.6)
project (mrz)
MESSAGE( STATUS "PROJECT_NAME: " ${PROJECT_NAME} )
# Check platforms
if (CMAKE_HOST_WIN32)
set(WINDOWS 1)
elseif(CMAKE_HOST_UNIX)
set(LINUX 1)
endif()
# Add search path for include and lib files
MESSAGE( STATUS "CPU architecture ${CMAKE_SYSTEM_PROCESSOR}" )
if(WINDOWS)
link_directories("${PROJECT_SOURCE_DIR}/platform/windows/lib/")
elseif(LINUX)
link_directories("${PROJECT_SOURCE_DIR}/platform/linux/")
endif()
include_directories("${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/include/")
# Add the executable
find_package(OpenCV REQUIRED)
add_executable(${PROJECT_NAME} mrzcv.cpp)
if(WINDOWS)
target_link_libraries (${PROJECT_NAME} "DynamsoftLabelRecognitionx64" ${OpenCV_LIBS})
else()
target_link_libraries (${PROJECT_NAME} "DynamsoftLabelRecognition" ${OpenCV_LIBS})
endif()
# Copy DLLs
if(WINDOWS)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/platform/windows/bin/"
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
endif()
DNN(심층 신경망)에서 훈련된 문자 모델은 C++ dev 패키지에서 찾을 수 있습니다. 전체 모델 폴더를 출력 디렉터리에 복사해야 하며 템플릿 파일도 마찬가지입니다.
# Copy template
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/template/"
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
# Copy model files
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/CharacterModel"
$<TARGET_FILE_DIR:${PROJECT_NAME}>/CharacterModel)
online documentation은 템플릿 매개변수가 작동하는 방식을 파악하는 데 도움이 될 수 있습니다.
MRZ 감지 및 정보 구문 분석을 위한 코딩
빌드 구성이 완료되면 코드 부분으로 이동할 수 있습니다.
OCR 개체를 초기화합니다. 유효한 라이센스 키가 필요합니다.
CLabelRecognition dlr;
dlr.InitLicense("LICENSE-KEY");
템플릿 파일을 추가합니다.
int ret = dlr.AppendSettingsFromFile("template-file");
참고: 템플릿 파일에 구성된
DirectoryPath
가 상대 경로인 경우 모델 폴더와 함께 템플릿 파일을 넣어야 합니다."CharacterModelArray" : [
{
"DirectoryPath": "CharacterModel",
"FilterFilePath": "",
"Name": "NumberUppercase"
}
],
OCR 인식 방법을 호출합니다. OpenCV의 내장 함수를 사용하여 통과 시간을 측정할 수 있습니다.
TickMeter
클래스는 Windows 및 Linux의 시간 계산 코드를 단순화합니다.TickMeter tm;
tm.start();
errorCode = dlr.RecognizeByFile(pszImageFile, "locr");
tm.stop();
float costTime = tm.getTimeSec();
텍스트 영역, 텍스트 라인 및 텍스트 문자열의 좌표를 포함하는 텍스트 인식 결과를 가져옵니다.
DLRResultArray* pDLRResults = NULL;
dlr.GetAllDLRResults(&pDLRResults);
if (pDLRResults != NULL)
{
int rCount = pDLRResults->resultsCount;
printf("\r\nRecognized %d results\r\n", rCount);
for (int ri = 0; ri < rCount; ++ri)
{
printf("\r\nResult %d :\r\n", ri);
int startX = 50, startY = 50;
DLRResult* result = pDLRResults->results[ri];
int lCount = result->lineResultsCount;
for (int li = 0; li < lCount; ++li)
{
printf("Line result %d: %s\r\n", li, result->lineResults[li]->text);
DLRPoint *points = result->lineResults[li]->location.points;
printf("x1: %d, y1: %d, x2: %d, y2: %d, x3: %d, y3: %d, x4: %d, y4: %d\r\n", points[0].x,
points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y);
}
}
}
else
{
printf("\r\nNo data detected.\r\n");
}
dlr.FreeDLRResults(&pDLRResults);
MRZ 문자열을 구문 분석하고 해당 정보를 추출합니다.
string line1 = result->lineResults[0]->text;
string line2 = result->lineResults[1]->text;
// https://en.wikipedia.org/wiki/Machine-readable_passport
// Type
string tmp = "Type: ";
tmp.insert(tmp.length(), 1, line1[0]);
printf("%s\r\n", tmp.c_str());
// Issuing country
tmp = "Issuing country: "; line1.substr(2, 5);
tmp += line1.substr(2, 3);
printf("%s\r\n", tmp.c_str());
// Surname
int index = 5;
tmp = "Surname: ";
for (; index < 44; index++)
{
if (line1[index] != '<')
{
tmp.insert(tmp.length(), 1, line1[index]);
}
else
{
break;
}
}
printf("%s\r\n", tmp.c_str());
// Given names
tmp = "Given Names: ";
index += 2;
for (; index < 44; index++)
{
if (line1[index] != '<')
{
tmp.insert(tmp.length(), 1, line1[index]);
}
else
{
tmp.insert(tmp.length(), 1, ' ');
}
}
printf("%s\r\n", tmp.c_str());
// Passport number
tmp = "Passport number: ";
index = 0;
for (; index < 9; index++)
{
if (line2[index] != '<')
{
tmp.insert(tmp.length(), 1, line2[index]);
}
else
{
break;
}
}
printf("%s\r\n", tmp.c_str());
// Nationality
tmp = "Nationality: ";
tmp += line2.substr(10, 3);
printf("%s\r\n", tmp.c_str());
// Date of birth
tmp = line2.substr(13, 6);
tmp.insert(2, "/");
tmp.insert(5, "/");
tmp = "Date of birth (YYMMDD): " + tmp;
printf("%s\r\n", tmp.c_str());
// Sex
tmp = "Sex: ";
tmp.insert(tmp.length(), 1, line2[20]);
printf("%s\r\n", tmp.c_str());
// Expiration date of passport
tmp = line2.substr(21, 6);
tmp.insert(2, "/");
tmp.insert(5, "/");
tmp = "Expiration date of passport (YYMMDD): " + tmp;
printf("%s\r\n", tmp.c_str());
// Personal number
if (line2[28] != '<')
{
tmp = "Personal number: ";
for (index = 28; index < 42; index++)
{
if (line2[index] != '<')
{
tmp.insert(tmp.length(), 1, line2[index]);
}
else
{
break;
}
}
printf("%s\r\n", tmp.c_str());
}
프로그램을 사용자에게 친숙하게 만들기 위해 OpenCV를 사용하여 디스플레이 창을 표시하고 관련 정보를 그립니다.
line( ori, Point(x1, y1), Point(x2, y2), lineColor, thickness);
line( ori, Point(x2, y2), Point(x3, y3), lineColor, thickness);
line( ori, Point(x3, y3), Point(x4, y4), lineColor, thickness);
line( ori, Point(x4, y4), Point(x1, y1), lineColor, thickness);
drawText(ori, result->lineResults[li]->text, minX, minY - scale * 10);
imshow("Passport MRZ Recognition", ori);
추가 개선 사항은
hconcat
기능을 사용하여 더 나은 비교를 위해 이미지를 연결하는 것입니다.hconcat(before, after, newMat);
imshow("Comparison", newMat);
소스 코드
https://github.com/yushulx/passport-mrz-recognition
Reference
이 문제에 관하여(Dynamsoft C++ OCR SDK를 이용한 여권 MRZ 인식), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/yushulx/passport-mrz-recognition-with-dynamsoft-c-ocr-sdk-2fkf텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)