Mistral OCR vs space-ocr 第2ラウンド — 誰もベンチマークしない写真で
space-ocr と Mistral OCR の統制ベンチマークを15ケース・14文書・769フィールドに拡張。精度と実行ごとの安定性、ビジョンLLMが回転した書類で崩れる様子、そして¥711が4行に印字されたレシートまで。
今月はじめ、Mistral Document AI との統制ベンチマークを公開した。同じ画像・同じ項目定義・同じ採点スクリプトを全エンジンに渡して、8ケース・463フィールドを3回ずつ走らせる、という内容だ。
あの記事には弱点がひとつあった。選んだのは読み取りが難しい「書類」だったが、実際の現場から届くのは難しい「写真」だという点だ。納品書は倉庫の床で横向きに撮られるし、レシートはポケットの中でシワになる。複写伝票は束のまま撮られ、上から判子が押してある。夜のバックヤードで、片手で、防犯モニターの灯りだけで撮られることもある。
そこで、まさにそういう写真を7ケース追加して、全部を測り直した。合計 15ケース・14文書・769フィールド、各エンジン3回ずつ。条件は前回と同じで、全エンジンに同じ画像と同じ項目定義を渡し、同じスクリプトで採点する。ひとつ変えたのは space-ocr 側の呼び方で、今回は社内経路ではなく公開API — どのアカウントも使っている POST /ocr/fields そのもの — を通して測った。つまりこの数字は、いま登録すれば誰でも同じ経路で再現できる数字だ。
| 769フィールド · 各3回 | space-ocr | Mistral OCR | ビジョンLLM (mistral-medium) |
|---|---|---|---|
| フィールド精度(完全一致) | 89.2% | 69.3% | 66.8% |
| 同じ入力を3回流したときの合計スコアの振れ幅 | 6フィールド | 106フィールド | 53フィールド |
表の読み方を二つ補足しておく。
まず、絶対値は控えめに見てほしい。正解データは一つの表記に固定してある。たとえば紙に「¥711」と印字されていれば正解も「¥711」で、エンジンが「711」と返せば不正解と数える。この種の表記ズレはどのエンジンにも起きるから、89.2% や 69.3% という絶対値はどれも実力の下限で、意味があるのは差のほうだ。
もうひとつは2行目の「振れ幅」。これは同じ写真の束を、何も変えずに3回読ませたとき、合計スコアが何フィールド動いたかという数字だ。space-ocr は3回で6フィールドしか動かなかった。Mistral OCR は106フィールド動いた — あるときは読めて、あるときは読めない値が106個分あったということだ。毎晩バッチで書類を流す使い方を考えると、この差は精度の差と同じくらい効いてくる。昨日と今日の出力の diff が「レビューできる差分」になるか「ただのノイズ」になるかの分かれ目だからだ。
差はどこで開くのか
下の表がこの記事の本体だ。いちばん条件のいい書類 — きれいに印刷された高密度の表 — では、実は3エンジンともほぼ満点で並ぶ。つまり「文字を認識する力」そのものには大差がない。差が開くのは、書類の構造が複雑になるときと、撮影条件が悪くなるときだ:
| 条件別スコア | space-ocr | Mistral OCR | ビジョンLLM |
|---|---|---|---|
| きれいな高密度印刷の表 | 1.000 | 0.986 | 0.960 |
| 商品名と数量が2行に分かれるレシート | 0.718 | 0.179 | 0.077 |
| ドットプリンタ伝票(横向きに撮影) | 0.872 | 0.778 | 0.217 |
| カーボン複写の束(横向き+判子) | 0.833 | 0.611 | 0.130 |
| 夜、クリップボードの上 | 0.831 | 0.488 | 0.441 |
| 暗い場所、シワだらけの伝票 | 0.912 | 0.898 | 0.830 |
この表でいちばん驚いた行は、横向きの2文書だ。ビジョンLLM — 写真をそのまま大規模言語モデルに渡して「この項目を抜き出して」と頼む方式 — が、回転した書類で崩壊する。 スコアは 0.217 と 0.130。同じ写真を、OCR を前段に持つ2エンジンは 0.611〜0.872 で読んでいる。
理由は仕組みを考えると腑に落ちる。OCR エンジンは文字を読む前に、ページの向きを検出してまっすぐに直す工程を持っている。ビジョンLLM にはその工程がなく、横倒しの画素がそのまま入ってくる。人間なら首を傾ければ済むが、モデルはページの大半を取り落とした。書類2枚の結果から一般法則を名乗るつもりはないので、正確に言う: このコーパスのこの2枚では、3回中3回、そうなった。
1枚のレシートに¥711が4つ
最後の新ケースは、少し毛色が違う。精度ではなく「座標はなぜ要るのか」を実物で示すケースだ。
セブン-イレブンのレシートで、711 という数字の並びが8箇所に出てくる。合計が¥711。iD支払も¥711。クレジット売上票の金額も¥711。税額の内訳行にも¥711。さらに、店の電話番号の末尾が 0711、レジを打った時刻が 07:11、日付が7月11日(2箇所)、伝票番号は 240-711-292-8686。偶然が全部この1枚に集まった。
このレシートに「合計」「iD支払額」「請求金額」の3項目を要求すると、正しく読めたエンジンは同じ「¥711」を3回返してくる。値を見ても、どれがどの行から来たのかは絶対に分からない。区別できる情報は座標だけだ。space-ocr の3回の実行では、3項目すべてが毎回それぞれ正しい行の上の枠を付けて返ってきて、枠の座標は3回とも同一だった。値しか返さないAPIには、そもそも「どの行を読んだか」を表明する場所がない。合っていても間違っていても、返ってくるJSONの見た目が同じになる。
コーパスを1つのギャラリーで
今回の測定で使った新しい写真の全部。リストから選んで見てほしい。緑の枠はすべてエンジンが実際に返した座標で、取引先の情報はこちらでモザイク処理してある。

それでも通り抜ける誤り
最後に、うまくいかなかった話も書いておく。
space-ocr の検証レイヤーは、モデルが返した値と、OCR がページ上で実際に見た文字を、独立した2つの目として突き合わせる仕組みだ。2つの目が一致しなければフラグが付く。ところが今回のような悪条件の写真では、残った誤りの大半が2つの目が同じ誤読で一致してしまうケースだった。グレアで白く飛んだ文字や、ブラーで溶けた文字は、どちらの読み手にも同じように誤って見える。突き合わせという仕組みの性質上、「合意された誤り」は捕まえられない。
これは以前から適用範囲外として明記してきた限界だが、今回それが実測で確認できた。だからレビューフラグは「人がどこを見るべきか」を絞り込むための信号であって、人の確認を置き換える保証ではない。金額の桁チェックや合計の検算のような業務ルールの層は、この上に重ねて使ってほしい。
この記事のすべての数字に付く但し書き: 15ケース・14文書・769フィールド・各3回実行・2026年8月・全エンジン同一画像/同一項目定義/同一採点・space-ocr は公開API経由で測定。コーパスは高密度の日本語ビジネス文書に寄っている(それが私たちの実トラフィックだからだ)。新しい写真には実在の取引先名や口座が印字されているため、公開は上のモザイク版のみ。測ったのはフィールド抽出だけで、マークダウン変換・速度・料金についての主張はない。
第1ラウンドの記事に、方法の全文と公開セットの生出力・採点ロジックがある。検証レイヤーそのものをどう測ったかは別の記事にまとめた。手元のいちばんひどい写真がどう読まれるか試したければ、ランディングページのデモがアカウントなしで1枚読んでくれる。