여권 이미지 / 멀티페이지 PDF

여권 파일 끌어놓기 또는 클릭하여 선택

PDF(멀티페이지 자동탐지), 클립보드 붙여넣기 지원

PoC 검증 평가 가이드

• 인식이 완료되면 결과 카드 하단에서 별점(1~5점)과 평가 코멘트를 남겨주세요.

• 남겨주신 의견은 관리자 대시보드에 실시간으로 취합되어 기술 방식 선정에 반영됩니다.

인식 결과가 여기에 표시됩니다

좌측에서 여권 이미지를 업로드하고 [인식 시작]을 누르면 엔진별 추출 결과 및 체크섬 검증 리포트를 확인하고 의견을 등록할 수 있습니다.

여권 OCR 테스트 히스토리 & 인식 결과 관리

과거 테스트 이력과 엔진별 상세 파싱 결과, 체크섬 검증 리포트 및 평가 의견을 조회·관리합니다.

관리자 의견 취합 및 PoC 비교 분석 대시보드

모든 테스터의 여권 인식 결과, 엔진별 만족도(별점), 정확도 및 의견을 한눈에 취합합니다.

인식 엔진별 핵심 성능 및 사용자 평가 비교표

테스터 의견 및 코멘트 실시간 취합 피드

여권 판독 API 사용법

여권 이미지 또는 PDF를 보내면 MRZ·VIZ 판독 결과를 JSON으로 돌려줍니다.

엔드포인트

메서드주소설명
POST/api/v1/passport/read여권 판독
GET/api/v1/engines지금 사용할 수 있는 엔진 목록
GET/api/v1/health서비스·영역 검출기 상태

인증은 현재 없습니다. 받는 파일: JPEG · PNG · WEBP · PDF(형식은 파일 내용으로 판별, 그 외는 415). PDF는 앞에서부터 검사해 MRZ가 있는 첫 페이지를 읽습니다(최대 100쪽). 본문 64 MiB 이하. 클라이언트 타임아웃은 120초 이상으로 두세요.

요청 방법

① 파일 그대로 보내기 — multipart/form-data (큰 PDF에 유리)
curl -X POST /api/v1/passport/read \
  -F "file=@passport.pdf" \
  -F "engine=rapidocr" \
  -F "regions=all"

파일 경로 앞의 @가 빠지면 파일이 아니라 경로 문자열이 전송되어 415 UNSUPPORTED_MEDIA가 납니다.

② base64로 보내기 — application/json
curl -X POST /api/v1/passport/read \
  -H "Content-Type: application/json" \
  -d '{
    "document": { "content_base64": "JVBERi0xLjQK...", "filename": "passport.pdf" },
    "engine": "rapidocr",
    "regions": "all",
    "options": { "include_crops": false, "include_raw_lines": true }
  }'
③ Python
import base64, requests

BASE = ""

# 엔진은 바뀔 수 있으니 먼저 목록을 확인
print(requests.get(f"{BASE}/api/v1/engines", timeout=10).json())

with open("passport.pdf", "rb") as f:
    content = base64.b64encode(f.read()).decode("ascii")

resp = requests.post(
    f"{BASE}/api/v1/passport/read",
    json={
        "document": {"content_base64": content, "filename": "passport.pdf"},
        "engine": "rapidocr",   # rapidocr | qwen3.6-35b | ppocrv6_gemma4
        "regions": "all",       # mrz | viz | all
    },
    timeout=180,
)
if resp.status_code == 200:
    r = resp.json()
    print(r["mrz"]["fields"]["document_number"], r["mrz"]["checksums"]["all_valid"])
    print(r["viz"]["fields"] if r["viz"] else None)
else:
    print(resp.status_code, resp.json()["error"])
파라미터값설명
file / document.content_base64파일 / base64필수. base64는 data:...;base64, 접두어·줄바꿈 허용
enginerapidocr · qwen3.6-35b · ppocrv6_gemma4선택, 생략하면 rapidocr(운영자 설정값). 목록은 /api/v1/engines에서 조회 (아래 표)
regionsmrz · viz · all선택, 생략하면 mrz(운영자 설정값). mrz는 기계판독영역만 읽어 가장 빠르고, 인쇄면까지 읽으려면 viz 또는 all을 지정
options.include_cropstrue / false선택, 기본 false. 교정된 MRZ/VIZ 크롭 PNG(base64)를 함께 반환
options.include_raw_linestrue / false선택, 기본 true. 엔진이 읽은 원문 줄을 함께 반환
지금 사용 가능한 엔진 (/api/v1/engines 실시간 조회)
불러오는 중...

응답 예시 (HTTP 200)

{
  "request_id": "5f0c2d1e-…",
  "engine": "rapidocr",
  "regions": "all",
  "document": { "filename": "passport.pdf", "pages": 5, "detected_page": 2 },
  "detection": {
    "detected": true, "backend": "hybrid",
    "mrz_found": true, "viz_found": true, "viz_status": "estimated", "review_needed": false
  },
  "mrz": {
    "success": true,
    "lines": [
      "P<LAODOUANGSOMPHOU<<PATTHANA<<<<<<<<<<<<<<<<",
      "P3231839<6LAO9004148M3502103<<<<<<<<<<<<<<<0"
    ],
    "fields": {
      "format": "TD3 (Passport)", "document_type": "P",
      "document_kind": { "kind": "passport", "name": "여권 (종류 표기 없음) / Passport", "note": "…" },
      "issuing_country": "LAO", "issuing_country_name": "라오스 (Laos)",
      "surname": "DOUANGSOMPHOU", "given_names": "PATTHANA", "full_name": "PATTHANA DOUANGSOMPHOU",
      "name_possibly_truncated": false,
      "document_number": "P3231839",
      "nationality": "LAO", "nationality_name": "라오스 (Laos)",
      "birth_date": "1990-04-14", "sex": "M", "expiry_date": "2035-02-10",
      "personal_number": ""
    },
    "checksums": {
      "document_number": true, "birth_date": true, "expiry_date": true,
      "optional_data": null, "composite": true, "all_valid": true
    },
    "format_checks": {
      "document_type": { "ok": true }, "issuing_country": { "ok": true }, "name": { "ok": true },
      "nationality": { "ok": true }, "sex": { "ok": true }, "all_ok": true
    },
    "warnings": [],
    "error": null
  },
  "viz": {
    "success": true,
    "fields": {
      "surname": "DOUANGSOMPHOU", "given_names": "PATTHANA", "document_number": "P3231839",
      "nationality": "LAO", "birth_date": "1990-04-14", "sex": "M",
      "issue_date": "2025-02-11", "expiry_date": "2035-02-10", "place_of_birth": "VIENTIANE"
    },
    "lines": ["Passport No", "P 3231839", "…"],
    "error": null
  },
  "timing_ms": { "detection": 2428, "engine": 3871, "model": 3100, "total": 6540 },
  "history_id": 312
}
필드뜻
detection검증된 MRZ를 찾았는지(detected), VIZ를 찾았는지(viz_found). MRZ를 못 찾으면 200 대신 422
mrz.lines읽은 두 줄. 항상 A-Z 0-9 <만 포함 (ICAO 9303). regions=viz면 mrz 전체가 null
mrz.fields파싱된 값. 날짜 YYYY-MM-DD(생년월일 미상 부분은 ??), 성별 M/F/X, 국가 ISO 3166-1 alpha-3 또는 ICAO 예외 코드(독일 D, 무국적 XXA 등). name_possibly_truncated=true면 이름이 잘렸을 수 있음. document_kind는 문서 코드가 뜻하는 여권 종류를 발급국 규칙으로 판정(중국은 2026년 4월 전후 코드가 달라 여권번호 첫 자리로 구분, 대한민국 PM·PS는 일반여권). 비자(MRV-A/B)와 TD2도 각자 규격으로 읽음
mrz.checksumsICAO 체크디짓 검증. 글자를 일관되게 읽었다는 뜻이며 진위 판정이 아님. optional_data는 개인번호 칸이 비었거나 규격에 없으면 null, composite는 비자면 null. all_valid는 그 규격의 체크디짓이 모두 맞을 때만 true. false면 사람이 확인
mrz.format_checks체크디짓이 없는 항목(여권 종류·발급국·성명·국적·성별)의 형식 검사. ok=true는 규격상 가능한 값이라는 뜻이며 판독 보증이 아님. ok=false면 issue에 이유(예: 성별 자리의 글자가 M·F·<가 아님, 코드표에 없는 국가 코드). all_ok는 다섯 항목 모두 ok
mrz.warnings / errorwarnings는 주의(결과 유효), error는 판독 실패 시에만(success=false)
viz.fields인쇄면(인적사항)에서 읽은 값, 영문 표기. 체크디짓이 없으므로 MRZ 값과 대조용. 못 읽은 항목은 없음. 부칭을 따로 인쇄하는 여권(우즈베키스탄 등)은 fathers_name에 담고 full_name에도 합침(이름 → 부칭 → 성). regions=mrz면 viz 전체가 null
timing_msdetection 영역 검출, engine 엔진 호출 전체, model 순수 추론, total 요청 전체
history_id이 호출의 이력 번호. "히스토리" 탭에서 사용자명 API로 확인 가능

오류 응답

{ "error": { "code": "NO_MRZ_DETECTED", "message": "…", "detail": { "pages": 5, "examined": [ … ] } } }
HTTPcode뜻할 일
400INVALID_REQUEST본문을 읽을 수 없거나 regions 값이 잘못됨요청 형식 확인
400INVALID_BASE64content_base64가 base64가 아님인코딩 확인
400UNKNOWN_ENGINE없는/꺼진 엔진. error.engines에 허용 목록목록에서 다시 선택
415UNSUPPORTED_MEDIAJPEG/PNG/WEBP/PDF가 아님, 또는 Content-Type이 JSON·multipart가 아님변환 후 재전송, curl은 @ 확인
422NO_MRZ_DETECTED어느 페이지에서도 검증된 2줄 MRZ를 못 찾음 (정상 미탐지, 판독 안 함)더 선명하게, 전체가 보이게 다시 촬영
502DETECTION_SERVICE_ERROR영역 검출 서비스가 응답하지 않음잠시 후 재시도, 지속되면 운영자 문의
503BUSY동시 처리 한도가 차서 대기 시간 안에 차례가 오지 않음 (요청은 정상)몇 초 뒤 같은 요청 재전송

엔진이 크롭을 받고도 읽지 못한 경우는 오류가 아니라 200에 mrz.success: false로 옵니다.