space ocr
文章文件
developer

一個會回傳可驗證定界框的 OCR API

多數 OCR API 都會回傳定界框——但座標系統各不相同,而一個框只告訴你位置,不告訴你有多確定。這是一份開發者導向的指南,談帶來源座標的 OCR,外加一個比對命中率,告訴你每個值有多少真的在頁面上被找到。

8 分鐘閱讀· 2026-06-25

定界框是你驗證 OCR 的方式。一個光禿禿的字串只告訴你模型認為它讀到了什麼;一個框則告訴你它是在頁面上的哪個位置讀到的,這樣你(或你的審核者,或你的程式碼)就能拿這個值去對照原件,而不必盲目相信。如果你要把 OCR 整合進任何會被稽核的東西——發票、費用、KYC、紀錄管理——「模型回傳了 total: 2,045」是不夠的;你得能指出 2,045 是從哪些像素來的。

好消息是:多數主流 OCR API 確實會回傳定界框。陷阱在於,一旦你開始動手做,它們有三個會帶來影響的差別——座標系統、你是不是也拿得到結構化欄位(而不只是純文字),以及那個逐值信心到底量的是什麼。本指南會把這三點都走一遍,並示範一個帶來源座標、外加一個字元覆蓋比對命中率的 OCR API 在實務上長什麼樣子。

先看證據:你可以滑過去驗證的框

這裡有一個真實的擷取結果,每一個值都指回它被讀出來的確切區域。把滑鼠移到任一欄位上——收據上的框就是那個值的來源,而且每個框都帶著一個比對命中率,告訴你這個值有多少文字真的在頁面上被定位到。

Source receipts with extracted-field bounding boxes
Verified fields
KINSHO · 合計 2,045
ライフ · 合計 4,286

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.

Demo每個欄位都回傳一個定界框和一個 <b>比對命中率</b>——正是這些座標,讓一次擷取變得可核對,而不只是看起來合理。
每個欄位都回傳一個定界框和一個 比對命中率——正是這些座標,讓一次擷取變得可核對,而不只是看起來合理。

多數 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,語言模型只回傳每個欄位的文字——外加它用到了哪些 word token 的提示——但從不自己給出那些框。引擎接著拿這段文字,去跟視覺 OCR 在頁面上實際偵測到的符號做字元層級的比對,於是框會落在這些字元真正被找到的像素上,而每個值也會得到一個 match_ratio,代表它被定位到的程度。那些 token 提示可能有雜訊(它有時會在重複的列之間張冠李戴),所以系統用欄一致性與列一致性檢查來驗證它們,而不是盲目相信。這就是「模型宣稱的座標」和「被拿回頁面上重新核對過的座標」之間的差別。

space-ocr 為每個值回傳什麼

在每個擷取出的值旁邊,你會拿到四樣東西,所以座標絕不只是一個你得選擇相信的數字:

  • bbox——一個軸對齊的矩形 { xmin, ymin, xmax, ymax },由整數組成,建立在 0–1000 正規化的網格上(0,0 = 左上,1000,1000 = 右下),與影像的像素尺寸無關。
  • 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 整合常見的一個 bug,是像素座標綁死在你上傳的那張影像上——為了存檔把它縮放或重新壓縮、或漏掉一個 EXIF 旋轉旗標,疊上去的框就會飄移、被裁切、或落在錯的文字上。正規化座標避開了這一整類 bug:一個 0–1000 的框能對應到同一頁面的任何一種呈現方式。

要在顯示的影像上畫一個框,只要轉換一次:

  • SVG 疊圖——給 SVG 設 viewBox="0 0 1000 1000",然後原封不動地畫出 bboxvertices
  • 絕對定位的 div——leftPct = xmin / 1000 * 100topPct = ymin / 1000 * 100widthPct = (xmax - xmin) / 1000 * 100heightPct = (ymax - ymin) / 1000 * 100
  • 轉回像素——pixel_x = bbox_x / 1000 * image_widthpixel_y = bbox_y / 1000 * image_height

引擎在載入時也會套用 EXIF 方向,所以它回傳的座標已經跟顯示出來的影像對齊——一張旋轉過的手機照片(方向 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 在伺服器端查詢它——wheresortselectlimitoffset——好抓出,比方說,每一列 match_ratio 偏低或 total >= 40000 的資料,不必重跑 OCR,也不另外收費。每個回傳的值都保留它的 bboxvertices(或者用 boxes=0 把它們丟掉,換一個更輕的回應)。想深入了解這套驗證流程,請看 用定界框驗證 OCROCR 稽核軌跡

Demo點選任一個值,它的來源區域就會在原件上亮起來——正是 API 回傳的那組座標,做成了可互動的形式。
點選任一個值,它的來源區域就會在原件上亮起來——正是 API 回傳的那組座標,做成了可互動的形式。

如何從這個 API 拿到可驗證的定界框

  1. 請求欄位
    把影像 POST 到 /ocr/fields,imageType 用「url」或「base64」,並附上一個 templateId 或你自己的 fields 陣列。引擎吃的是點陣影像(JPEG、PNG、GIF、BMP、TIFF、WebP)。
  2. 讀取座標
    每個值都回傳一個 0–1000 網格上的 bbox { xmin, ymin, xmax, ymax }、四個有方向的 vertices、一個 match_ratio,以及一個 bbox_source。
  3. 疊圖或轉換
    用一個 viewBox「0 0 1000 1000」的 SVG 畫出框,或用 pixel_x = bbox_x / 1000 * image_width 轉成像素。EXIF 旋轉已經套用過,所以框會跟顯示的影像對齊。
  4. 以比對命中率設閘門
    把 0.85 以上的 match_ratio 當成高信心命中;任何低於這個的就浮出來給人看一眼,而不是把每個值都重查一遍。
  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 回傳的 bbox 正規化到一個 0–1000 的網格,與影像的像素尺寸無關,外加四個有方向的 vertices。用 pixel_x = bbox_x / 1000 * image_width(y 也一樣)轉成像素,或直接用一個 viewBox 為「0 0 1000 1000」的 SVG 來疊圖。正規化座標撐得過影像縮放,而某些其他引擎的像素座標撐不過。
一個 OCR 信心分數和一個比對命中率有什麼差別?
辨識信心反映的是引擎對自己讀法有多確定。一個 match_ratio 量的是回傳值的文字有多少真的在頁面層級 OCR 偵測到的符號之中被定位到——是一項外部檢查,而不是自我回報。space-ocr 把 match_ratio 在 0.85 以上的值視為高信心命中,所以你可以針對偏低的那些設下閘門。
我能為歪斜或旋轉的照片拿到有方向的定界框嗎?
可以。每個值都回傳四個有序的頂點(左上、右上、右下、左下),組成一個跟著文件傾斜角度走的有方向定界框。引擎在載入時也會套用 EXIF 方向,所以座標已經跟顯示的影像對齊——一張方向為 6 或 8 的手機照片,不需要你這邊再做一次校正。
這套定界框 OCR 對日文、韓文和中文有效嗎?
有效。同一個引擎以自動語言偵測處理中日韓與拉丁文字——沒有語言參數要設——並且不論文字種類,都為每個值回傳一樣的 bbox、vertices 和 match_ratio,包括全形字元和直書漢字。

為每一個值拿到來源座標

免費方案——每月 100 次掃描,免綁信用卡。每個欄位都回傳一個定界框、有方向的頂點,以及一個比對命中率。

相關文章