검증 가능한 바운딩 박스를 반환하는 OCR API
대부분의 OCR API는 바운딩 박스를 반환합니다 — 하지만 좌표계가 제각각이고, 박스는 어디인지만 알려줄 뿐 얼마나 확실한지는 알려주지 않습니다. 원본 좌표를 다루는 OCR 개발자 가이드, 그리고 각 값이 실제로 페이지에서 얼마나 발견되었는지 알려주는 일치 비율(match ratio)까지.
바운딩 박스는 OCR을 검증하는 수단입니다. 단순한 문자열은 모델이 무엇을 읽었다고 생각하는지만 알려주지만, 박스는 그것을 페이지의 어디서 읽었는지 알려줍니다. 덕분에 여러분(혹은 검토자, 혹은 코드)이 그 값을 무작정 믿는 대신 원본과 대조할 수 있습니다. 감사 대상이 되는 무언가에 OCR을 통합하고 있다면 — 세금계산서, 경비, KYC, 기록 관리 — "모델이 total: 2,045를 반환했다"는 것만으로는 부족합니다. 그 2,045가 나온 픽셀을 가리킬 수 있어야 합니다.
좋은 소식: 대부분의 주류 OCR API는 바운딩 박스를 반환합니다. 함정은 막상 만들기 시작하면 중요해지는 세 가지 측면에서 서로 다르다는 점입니다 — 좌표계, 정형 필드(원시 텍스트뿐 아니라)까지 함께 주는지 여부, 그리고 값별 신뢰도가 실제로 무엇을 측정하는지. 이 가이드는 세 가지를 모두 짚어 보고, 원본 좌표에 글자 커버리지 기반 일치 비율까지 더한 OCR API가 실제로 어떤 모습인지 보여드립니다.
먼저 증거: 마우스를 올려 확인할 수 있는 박스
여기 모든 값이 그것이 읽힌 정확한 영역으로 되짚어지는 실제 추출 결과가 있습니다. 어느 항목이든 마우스를 올려 보세요 — 영수증 위의 박스가 바로 그 값의 출처이며, 각 박스는 값의 텍스트가 페이지에서 실제로 얼마나 발견되었는지를 나타내는 *일치 비율(match ratio)*을 함께 담고 있습니다.

Every value carries a verified on-page location — bbox + 4-point vertices + match_ratio — on a 0–1000 normalized grid (0,0 top-left → 1000,1000 bottom-right), the same shape the live API returns. Hover a field to trace it back to the pixels it came from.
대부분의 OCR API는 박스를 반환합니다 — 차이는 여기에 있습니다
Google Cloud Vision, Tesseract, Amazon Textract, Azure AI Document Intelligence는 모두 텍스트와 함께 기하 정보를 반환합니다. 다만 좌표계, 정형 필드를 주는지 아니면 원시 텍스트 + 레이아웃만 주는지, 그리고 신뢰도 숫자가 무엇을 의미하는지에서 갈립니다. 이는 마케팅이 아니라 검증된 사실입니다 — 여러분 스택에서 통합 작업량을 가늠하는 데 활용하세요.
| API | 좌표계 | 정형 필드 | 값별 신뢰도 |
|---|---|---|---|
| Google Cloud Vision | boundingPoly 꼭짓점, 원본 이미지의 픽셀 단위 | 텍스트 + 기하 정보만 (정형 키-값은 별도 제품인 Google Document AI) | 단어/심볼별 인식 신뢰도 (0–1) |
| Tesseract | hOCR / TSV 박스, 픽셀 단위 (자체 호스팅, API 없음) | 없음 — 원시 텍스트 + 레이아웃 | 단어별 인식 신뢰도 (0–100) |
| Amazon Textract | BoundingBox, 페이지 너비/높이 기준 0–1 정규화 (+ Polygon) | AnalyzeDocument로 폼/표; AnalyzeExpense로 영수증 | 블록별 인식 신뢰도 (%) |
| Azure Document Intelligence | 바운딩 폴리곤, 픽셀(이미지) 또는 인치(PDF) | 사전 구축/맞춤 모델 | 단어별 인식 신뢰도 |
| space-ocr | bbox 0–1000 정규화 (+ 방향이 있는 vertices) | 내장 템플릿 + 맞춤 필드, 품목 행 지원 | match_ratio — 값의 글자 중 페이지에서 발견된 비율 — + bbox_source |
두 가지를 눈여겨보세요. 첫째, 좌표 단위는 이식 가능하지 않습니다 — Vision/Tesseract/Azure의 픽셀 박스는 여러분이 보낸 바로 그 이미지에 묶여 있는 반면, 정규화 박스(Textract, space-ocr)는 크기 변경에도 살아남습니다. 둘째, 신뢰도 열은 서로 다른 것을 의미합니다 — 대부분의 API는 인식 신뢰도(모델이 얼마나 확신하는지)를 보고하는데, 이는 반환된 값이 실제로 페이지에서 얼마나 발견되었는지를 측정하는 것과는 다릅니다.
박스가 어떤 형식인지만큼이나, 그 박스가 어떻게 도출되는지가 중요합니다. space-ocr에서 언어 모델은 각 필드의 텍스트와 — 어떤 단어 토큰을 사용했는지에 대한 힌트를 — 반환하지만, 박스 자체는 절대 만들어내지 않습니다. 엔진은 그 텍스트를 비전 OCR이 페이지에서 실제로 검출한 심볼과 글자 단위로 대조하므로, 박스는 그 글자들이 발견된 실제 픽셀 위에 놓이고, 각 값에는 얼마나 발견되었는지를 나타내는 match_ratio가 부여됩니다. 토큰 힌트는 노이즈가 있을 수 있어(반복되는 행 사이에서 토큰을 바꿔치기도 합니다), 무작정 믿는 대신 열·행 일관성 검사로 이를 검증합니다. 이것이 모델이 주장하는 좌표와, 페이지에 되짚어 대조된 좌표의 차이입니다.
space-ocr가 모든 값에 대해 반환하는 것
추출된 각 값과 함께 네 가지를 받게 되므로, 좌표는 결코 무작정 믿어야 하는 숫자에 그치지 않습니다.
bbox— 이미지의 픽셀 크기와 무관하게 0–1000 정규화 격자(0,0 = 좌상단, 1000,1000 = 우하단) 위에 놓인 정수 값의 축 정렬 사각형{ xmin, ymin, xmax, ymax }.vertices— 문서의 기울기를 따라가는 방향이 있는 박스를 이루는, 정확히 네 개의 순서가 정해진 점(좌상단, 우상단, 우하단, 좌하단). 덕분에 비뚤어진 휴대폰 사진도 깔끔하게 박스가 잡힙니다.match_ratio— 값의 글자 중 실제로 페이지에서 발견된 비율(0–1). 필드는 ≥ 0.85에서 확실히 매칭된 것으로 간주하며,1.0은 모든 글자를 찾았다는 뜻입니다.bbox_source— 좌표가 어떻게 도출되었는지를 나타내는 라벨(예: 글자 대조 경로의 경우vision_symbol_match, 일치 비율이 임계값 아래로 떨어지면low_confidence).
{
"total": {
"value": "2,045",
"bbox": { "xmin": 381, "ymin": 803, "xmax": 500, "ymax": 825 },
"vertices": [
{ "x": 380, "y": 804 }, { "x": 500, "y": 801 },
{ "x": 500, "y": 823 }, { "x": 381, "y": 826 }
],
"match_ratio": 1.0,
"bbox_source": "vision_symbol_match"
}
}픽셀이냐 정규화냐? 한 번만 변환하면 크기 변경에 깨지지 않습니다
OCR 통합에서 반복되는 버그는 픽셀 좌표가 여러분이 업로드한 바로 그 이미지에 묶여 있다는 점입니다 — 저장을 위해 크기를 바꾸거나 재압축하거나, EXIF 회전 플래그를 놓치면, 겹쳐 그린 박스가 어긋나거나 잘리거나 엉뚱한 텍스트에 떨어집니다. 정규화 좌표는 이런 부류의 버그를 통째로 피해 갑니다. 0–1000 박스는 같은 페이지를 어떻게 렌더링하든 그 위에 매핑됩니다.
표시된 이미지에 박스를 그리려면 한 번만 변환하세요.
- SVG 오버레이 — SVG에
viewBox="0 0 1000 1000"을 주고bbox/vertices를 그대로 그립니다. - 절대 위치 div —
leftPct = xmin / 1000 * 100,topPct = ymin / 1000 * 100,widthPct = (xmax - xmin) / 1000 * 100,heightPct = (ymax - ymin) / 1000 * 100. - 다시 픽셀로 —
pixel_x = bbox_x / 1000 * image_width,pixel_y = bbox_y / 1000 * image_height.
엔진은 로드 시 EXIF 방향도 적용하므로, 반환되는 좌표는 이미 표시되는 이미지와 일치합니다 — 회전된 휴대폰 사진(orientation 6/8)도 여러분 쪽에서 보정 작업을 거칠 필요가 없습니다.
curl -s https://api.space-ocr.com/ocr/fields \
-H "Authorization: Bearer $SPACE_OCR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "https://example.com/receipt.jpg",
"imageType": "url",
"fields": [
{ "name": "vendor", "type": "string" },
{ "name": "total", "type": "string" }
]
}'신뢰도 점수와 일치 비율은 같은 것이 아닙니다
이것이 꼭 체득해 둘 만한 구분입니다. 대부분의 OCR API는 인식 신뢰도를 문서화합니다 — 글꼴의 선명함이나 이미지 품질 같은 요소를 바탕으로, 엔진이 자기 읽기에 대해 얼마나 확신하는지를 반영하는 숫자입니다. 유용하긴 하지만, 모델이 자기 숙제를 자기가 채점하는 격입니다. 일치 비율은 외부적인 무언가를 측정합니다. 모델이 반환한 값의 글자 중, 페이지 단위 OCR이 검출한 심볼 사이에서 실제로 발견된 것이 몇 개인지입니다. 어떤 값은 인식 신뢰도와 함께 반환되더라도 페이지의 무엇과도 들어맞지 않을 수 있는데, 낮은 match_ratio가 바로 그것을 잡아냅니다. 이를 게이트로 활용하세요 — 모든 것을 다시 검토하는 대신, match_ratio < 0.85로 정렬하거나 필터링해서 사람이 한 번 들여다볼 만한 소수의 값을 드러내세요.
검증한 뒤 — OCR을 다시 돌리지 않고 조회하기
좌표는 데이터가 남아 있을 때 가장 쓸모가 있습니다. POST /upload로 이미지를 시트에 밀어 넣은 뒤, GET /view로 서버 측에서 조회하세요 — where, sort, select, limit, offset — 예를 들어 match_ratio가 낮거나 total >= 40000인 모든 행을, OCR 재실행도 추가 비용도 없이 가져올 수 있습니다. 반환되는 각 값은 bbox/vertices를 그대로 유지합니다(가벼운 페이로드를 원하면 boxes=0으로 빼세요). 검증 워크플로를 깊이 다룬 내용은 바운딩 박스로 OCR 검증하기와 OCR 감사 추적을 참고하세요.
API에서 검증 가능한 바운딩 박스를 얻는 방법
- 필드 요청하기imageType을 'url' 또는 'base64'로 하여 이미지를 /ocr/fields에 POST 하고, templateId 또는 직접 만든 fields 배열을 함께 넘깁니다. 엔진은 래스터 이미지(JPEG, PNG, GIF, BMP, TIFF, WebP)를 받습니다.
- 좌표 읽기각 값은 0–1000 격자 위의 bbox { xmin, ymin, xmax, ymax }, 방향이 있는 네 개의 vertices, match_ratio, 그리고 bbox_source를 반환합니다.
- 겹쳐 그리거나 변환하기'0 0 1000 1000' SVG viewBox로 박스를 그리거나, pixel_x = bbox_x / 1000 * image_width로 픽셀로 변환합니다. EXIF 회전은 이미 적용되어 있어 박스가 표시되는 이미지와 일치합니다.
- 일치 비율에 게이트 걸기match_ratio가 0.85 이상이면 확실한 매칭으로 간주하고, 그 미만은 모든 값을 다시 검토하는 대신 사람이 한 번 들여다볼 수 있도록 드러냅니다.
- 저장하고 조회하기/upload로 이미지를 시트에 밀어 넣고 GET /view(where, sort, select)로 조회합니다 — 좌표는 그대로 유지되며 OCR 재실행도 추가 비용도 없습니다.
어떤 OCR API가 바운딩 박스를 반환하나요?
바운딩 박스 좌표는 픽셀인가요, 정규화된 값인가요?
OCR 신뢰도 점수와 일치 비율의 차이는 무엇인가요?
비뚤어지거나 회전된 사진에서도 방향이 있는 바운딩 박스를 얻을 수 있나요?
이 바운딩 박스 OCR이 일본어, 한국어, 중국어에서도 작동하나요?
모든 값에 대해 원본 좌표를 받으세요
무료 플랜 — 신용카드 없이 월 100회 스캔. 모든 항목이 바운딩 박스, 방향이 있는 vertices, 그리고 일치 비율과 함께 반환됩니다.