space ocr
指南文章價格文件
developer

從掃描檔取出人會閱讀的那個順序的文字

用 POST /ocr/text 擷取閱讀順序純文字,並按需取得只含內容的 blocks、以 path 索引的原圖座標與明確的覆核清單。

7 分鐘閱讀· 2026-08-31

「只要把文字給我」聽起來是最簡單的 OCR 要求,卻也最容易悄悄破壞搜尋索引。視覺 OCR 可能找對每個詞,卻按偵測順序回傳:左欄第一行、右欄第一行、再回到左欄。系統沒有報錯,文件卻不再是人能順著讀的文件。

POST /ocr/text 把這個問題與欄位擷取、Markdown 轉換分開處理。預設的 useLlm: true 會按人的閱讀順序重排區塊,並重新連接因換行斷開的內容。同時,文字與來源位置仍和 Vision 觀測交叉核對,不會把語言模型的轉寫無條件當成真值。

控制請求的兩個開關

useLlm 預設為 true。多欄排版、側欄、傾斜掃描,或要交給人閱讀的文字,都應保持開啟。設為 false 時會跳過 LLM 步驟,按 raw OCR 順序回傳純 Vision 轉寫;這條路徑仍會回傳文件級驗證物件。

includeBlocks 預設為 false。只需要全文時讀取 data.values.text 即可。需要自行分塊、在原圖標示或製作覆核介面時再開啟。開啟後會增加只含內容的 data.values.blocks、形如 data.cells["blocks[0]"] 的中繼資料,以及 data.review.flagged 裡的區塊 path。

一次請求

下面開啟 includeBlocks,以便把待覆核文字追溯到原圖。驗證與完整參數請見 API 文件

1
2
3
4
5
6
7
8
9
curl -X POST https://api.space-ocr.com/ocr/text \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://example.com/page.jpg",
    "imageType": "url",
    "useLlm": true,
    "includeBlocks": true
  }'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
  "status": "success",
  "data": {
    "values": {
      "text": "櫻花貿易有限公司\n發票\n合計 1,451元",
      "blocks": [
        {
          "text": "櫻花貿易有限公司"
        },
        {
          "text": "發票\n合計 1,451元"
        }
      ]
    },
    "cells": {
      "blocks[0]": {
        "box": {
          "xmin": 60,
          "ymin": 48,
          "xmax": 470,
          "ymax": 92
        },
        "quad": [
          {
            "x": 60,
            "y": 48
          },
          {
            "x": 470,
            "y": 48
          },
          {
            "x": 470,
            "y": 92
          },
          {
            "x": 60,
            "y": 92
          }
        ],
        "verified": true,
        "review": null,
        "evidence": {
          "text_match": true,
          "source": "token_id"
        }
      },
      "blocks[1]": {
        "box": {
          "xmin": 58,
          "ymin": 190,
          "xmax": 510,
          "ymax": 274
        },
        "quad": [
          {
            "x": 58,
            "y": 190
          },
          {
            "x": 510,
            "y": 190
          },
          {
            "x": 510,
            "y": 274
          },
          {
            "x": 58,
            "y": 274
          }
        ],
        "verified": false,
        "review": {
          "reasons": [
            "text_mismatch"
          ]
        },
        "evidence": {
          "text_match": false,
          "source": "char_matcher_fallback"
        }
      }
    },
    "review": {
      "unit": "block",
      "total": 2,
      "boxed": 2,
      "verified": 1,
      "flagged": [
        {
          "path": "blocks[1]",
          "reasons": [
            "text_mismatch"
          ]
        }
      ],
      "by_reason": {
        "text_mismatch": 1
      },
      "coverage": {
        "recovered_blocks": 0,
        "vision_tokens": 8,
        "tokens_claimed": 8,
        "token_coverage": 1
      }
    },
    "image": {
      "width": 1654,
      "height": 2339
    },
    "source": "llm"
  }
}

按責任讀取回應

  • data.values.text 是全文。開啟 blocks 後,相同內容也會按 { text } 單元放在 data.values.blocks,內容中不混入座標。
  • data.cells[path] 是原圖證據的旁路資料。boxquad 使用 0~1000 頁面座標,可結合 data.image.widthheight 投影到處理後影像。verified 表示區塊與對應位置的 Vision 文字在正規化後是否一致,不是準確率百分比。
  • data.review.flagged 是實際覆核清單。每個 path 都能直接查找 data.cells[path]review.reasons 說明建議檢查的原因。
  • data.source 在閱讀順序路徑中為 llm,在 Vision 路徑中為 vision

索引程式可以只使用 values.text,覆核介面則使用 reviewcells,不必從正文拆出座標。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const { data } = await response.json();

indexDocument(data.values.text);

for (const flag of data.review.flagged) {
  const cell = data.cells?.[flag.path];
  queueForReview({
    path: flag.path,
    reasons: flag.reasons,
    box: cell?.box,
    quad: cell?.quad,
    image: data.image,
  });
}
✓ Verified

回退不會被隱藏。 LLM 閱讀順序步驟失敗時,端點不會把它變成 OCR 錯誤,而會回傳 Vision 轉寫。此時 data.source"vision",原因寫入 data.warning。未被任何區塊認領的 Vision token 也可能成為 cells[path].evidence.source: "unclaimed_tokens" 的回收區塊,讓遺漏顯示出來而非悄悄丟棄。

選純文字還是 Markdown

全文搜尋、向量化、差異比較、無障礙資訊流等場景,若不需要把標題和表格保留為獨立類型,純文字更合適。需要結構時改用 POST /ocr/markdown影像轉 Markdown 指南介紹它的元素回應。座標與覆核中繼資料可繼續閱讀 OCR 原圖座標

  1. 選擇閱讀順序路徑
    把影像送到 POST /ocr/text。閱讀順序重要時保留預設 useLlm:true,只有 raw Vision 順序可接受時才設為 false。
  2. 需要來源證據時要求 blocks
    設定 includeBlocks:true,取得 values.blocks、以 path 索引的 cells 與區塊級 review;只需全文時維持預設值。
  3. 處理明確的覆核清單
    巡覽 data.review.flagged,用 data.cells[flag.path] 取出 box 或 quad,並繪製在 data.image 描述的影像框架上。
  4. 記錄實際轉寫路徑
    把 data.source 與正文一起保存;自動回退為 vision 時向操作人員顯示 data.warning。
/ocr/text 預設會修正閱讀順序嗎?
會。useLlm 預設為 true,會重新排列區塊並連接換行斷開的內容。只有更需要 raw OCR 順序的 Vision 轉寫時才設為 false。
一定要要求 blocks 嗎?
不用。includeBlocks 預設為 false,簡單索引只讀取 data.values.text 即可。需要 blocks[n] 座標與區塊級覆核時再開啟。
verified:true 能保證區塊正確嗎?
不能。它表示區塊文字與連結座標處的 Vision 文字在正規化後相符,不是準確率分數;兩個讀取仍可能一致地誤讀。
閱讀順序模型失敗時會怎樣?
端點會回退到 Vision 轉寫,把 data.source 設為 vision,並在 data.warning 說明原因;文件級 data.review 仍會回傳。
相關文章