space ocr
가이드아티클요금문서
developer

검증 가능한 바운딩 박스를 반환하는 OCR API

대부분의 OCR API는 바운딩 박스를 반환합니다. 하지만 좌표계가 제각각인 데다, 박스는 위치만 알려줄 뿐 얼마나 확실한지는 알려주지 않습니다. 원본 좌표를 다루는 개발자용 OCR 가이드이자, 각 값이 페이지에서 실제로 얼마나 발견되었는지 알려주는 일치 비율(match ratio)까지 짚어 봅니다.

8 분 분량· 2026-06-25

바운딩 박스는 OCR을 검증하는 단서입니다. 단순한 문자열은 모델이 무엇을 읽었다고 여기는지만 알려주지만, 박스는 그것을 페이지의 어디서 읽었는지까지 알려줍니다. 그래서 여러분(혹은 검토자, 혹은 코드)이 그 값을 무작정 믿는 대신 원본과 대조해 볼 수 있습니다. 세금계산서, 경비, KYC, 기록 관리처럼 감사 대상이 되는 곳에 OCR을 붙인다면, "모델이 total: 2,045를 반환했다"는 것만으로는 부족합니다. 그 2,045가 어느 픽셀에서 나왔는지 가리킬 수 있어야 합니다.

다행히 주요 OCR API는 대부분 바운딩 박스를 반환합니다. 문제는 막상 개발에 들어가면 중요해지는 세 가지에서 저마다 다르다는 점입니다. 바로 좌표계, (원시 텍스트뿐 아니라) 정형 필드까지 함께 주는지, 그리고 값별 신뢰도가 실제로 무엇을 재는지입니다. 이 가이드는 이 세 가지를 차례로 짚어 보고, 원본 좌표에 글자 커버리지 기반 일치 비율까지 더한 OCR API가 실제로 어떤 모습인지 보여 드립니다.

대부분의 OCR API는 박스를 반환합니다 — 차이는 여기에 있습니다

Google Cloud Vision, Tesseract, Amazon Textract, Azure AI Document Intelligence는 모두 텍스트와 함께 기하 정보를 반환합니다. 다만 좌표계, 정형 필드를 주는지 아니면 원시 텍스트와 레이아웃만 주는지, 그리고 신뢰도 숫자가 무엇을 뜻하는지에서 갈립니다. 마케팅 문구가 아니라 검증된 사실이니, 여러분 스택에서 통합에 얼마나 손이 갈지 가늠하는 데 활용하세요.

API좌표계정형 필드값별 신뢰도
Google Cloud VisionboundingPoly 꼭짓점, 원본 이미지의 픽셀 단위텍스트 + 기하 정보만 (정형 키-값은 별도 제품인 Google Document AI)단어/심볼별 인식 신뢰도 (0–1)
TesseracthOCR / TSV 박스, 픽셀 단위 (자체 호스팅, API 없음)없음 — 원시 텍스트 + 레이아웃단어별 인식 신뢰도 (0–100)
Amazon TextractBoundingBox, 페이지 너비/높이 기준 0–1 정규화 (+ Polygon)AnalyzeDocument로 폼/표; AnalyzeExpense로 영수증블록별 인식 신뢰도 (%)
Azure Document Intelligence바운딩 폴리곤, 픽셀(이미지) 또는 인치(PDF)사전 구축/맞춤 모델단어별 인식 신뢰도
space-ocrbbox 0–1000 정규화 (+ 방향이 있는 vertices)내장 템플릿 + 맞춤 필드, 품목 행 지원match_ratio — 값의 글자 중 페이지에서 발견된 비율 — + bbox_source

두 가지를 눈여겨보세요. 첫째, 좌표 단위는 그대로 옮겨 쓸 수 없습니다. Vision/Tesseract/Azure의 픽셀 박스는 여러분이 보낸 바로 그 이미지에 묶여 있는 반면, 정규화 박스(Textract, space-ocr)는 크기를 바꿔도 살아남습니다. 둘째, 신뢰도 열이 가리키는 것은 저마다 다릅니다. 대부분의 API가 보고하는 것은 인식 신뢰도(모델이 얼마나 확신하는지)인데, 이는 반환된 값이 페이지에서 실제로 얼마나 발견되었는지를 재는 것과는 다릅니다.

✓ Verified

박스가 어떤 형식인지만큼이나, 그 박스를 어떻게 끌어내는지가 중요합니다. 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).
반환된 값 하나
1
2
3
4
5
6
7
8
9
10
11
12
{
  "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를 그대로 그립니다.
  • 절대 위치 divleftPct = 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)도 여러분 쪽에서 따로 보정할 필요가 없습니다.

필드를 요청하고 좌표를 돌려받기
1
2
3
4
5
6
7
8
9
10
11
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가 반환하는 바로 그 좌표를 그대로 인터랙티브하게 만든 것입니다.

API에서 검증 가능한 바운딩 박스를 얻는 방법

  1. 필드 요청하기
    imageType을 'url' 또는 'base64'로 지정해 이미지를 /ocr/fields에 POST 하고, templateId나 직접 만든 fields 배열을 함께 넘깁니다. 엔진이 받는 것은 래스터 이미지(JPEG, PNG, GIF, BMP, TIFF, WebP)입니다.
  2. 좌표 읽기
    각 값은 0–1000 격자 위의 bbox { xmin, ymin, xmax, ymax }, 방향이 있는 네 개의 vertices, match_ratio, 그리고 bbox_source를 반환합니다.
  3. 겹쳐 그리거나 변환하기
    '0 0 1000 1000' SVG viewBox로 박스를 그리거나, pixel_x = bbox_x / 1000 * image_width로 픽셀로 바꿉니다. EXIF 회전은 이미 적용되어 있어 박스가 표시되는 이미지와 일치합니다.
  4. 일치 비율에 게이트 걸기
    match_ratio가 0.85 이상이면 확실한 매칭으로 보고, 그 미만은 모든 값을 다시 검토하는 대신 사람이 한 번 들여다보도록 드러냅니다.
  5. 저장하고 조회하기
    /upload로 이미지를 시트에 밀어 넣고 GET /view(where, sort, select)로 조회합니다. 좌표는 그대로 유지되고, OCR 재실행도 추가 비용도 없습니다.
어떤 OCR API가 바운딩 박스를 반환하나요?
Google Cloud Vision, Tesseract, Amazon Textract, Azure AI Document Intelligence는 모두 텍스트와 함께 기하 정보를 반환하며, space-ocr도 그렇습니다. 다만 좌표계(Vision, Tesseract, Azure는 픽셀, Textract는 0–1 정규화, space-ocr는 0–1000 정규화), 정형 필드를 돌려주는지 아니면 원시 텍스트와 레이아웃만 주는지, 그리고 값별 신뢰도가 무엇을 재는지에서 차이가 납니다.
바운딩 박스 좌표는 픽셀인가요, 정규화된 값인가요?
space-ocr는 이미지의 픽셀 크기와 무관하게 0–1000 격자에 정규화된 bbox와, 방향이 있는 네 개의 vertices를 반환합니다. 픽셀로 바꾸려면 pixel_x = bbox_x / 1000 * image_width(y도 동일)를 쓰면 되고, '0 0 1000 1000' SVG viewBox로 곧장 겹쳐 그릴 수도 있습니다. 정규화 좌표는 이미지 크기를 바꿔도 살아남지만, 일부 다른 엔진의 픽셀 좌표는 그렇지 못합니다.
OCR 신뢰도 점수와 일치 비율의 차이는 무엇인가요?
인식 신뢰도는 엔진이 자기 읽기에 얼마나 확신하는지를 나타냅니다. 반면 match_ratio는 반환된 값의 텍스트가 페이지 단위 OCR이 검출한 심볼 사이에서 실제로 얼마나 발견되었는지를 잽니다. 자기 보고가 아니라 바깥에서 하는 검사인 셈입니다. space-ocr는 match_ratio가 0.85 이상이면 확실한 매칭으로 보므로, 낮은 값들에 게이트를 걸 수 있습니다.
비뚤어지거나 회전된 사진에서도 방향이 있는 바운딩 박스를 얻을 수 있나요?
네. 모든 값이 문서의 기울기를 따라가는 방향 있는 박스를 이루는, 순서가 정해진 네 개의 vertices(좌상단, 우상단, 우하단, 좌하단)를 반환합니다. 엔진은 로드할 때 EXIF 방향도 적용하므로 좌표는 처음부터 표시되는 이미지와 일치합니다. orientation 6 또는 8인 휴대폰 사진도 여러분 쪽에서 따로 보정할 필요가 없습니다.
이 바운딩 박스 OCR이 일본어, 한국어, 중국어에서도 작동하나요?
네. 하나의 엔진이 자동 언어 감지로 한중일(CJK)과 라틴 문자를 모두 처리합니다. 따로 설정할 언어 파라미터는 없습니다. 전각 문자와 세로쓰기 한자를 포함해 어떤 문자든, 모든 값에 같은 bbox, vertices, match_ratio를 반환합니다.
관련 글