【検証レポート】Mistral OCRで日本語文書をスキャンして試してみた感想と使い方

先日Xで少し話題となっていたMistral OCR
X上ではかなり精度が高いと言われていましたが、公式を見ると日本語のスコアがなく、実際日本語の資料でどれくらい使えるかがわかりませんでした。
なので、今回は日本でよくある資料を用いて検証してみようと思います!

セットアップから実行まで
Mistral OCRを使うための準備は簡単です(Pythonでの実行環境がセットアップされている前提です)。
公式ドキュメントはこちら
- MistralコンソールからAPIキーを発行
pip install mistralai
でパッケージをインストール- 下記のコードを実行
今回はローカルのPDFファイルをmistral上にアップし、presigned_urlを取得→ocrを行い、ローカルで結果が確認できるよう、画像やmdファイルを適切に保存されるように実装しました
import os
from mistralai import Mistral
from mistralai.models import OCRResponse
import base64
from datetime import datetime
from pathlib import Path
api_key = "API_KEY"
target_filename = "TARGET_FILE_NAME"
client = Mistral(api_key=api_key)
def save_image(image_base64: str, image_path: str) -> bool:
"""
Base64エンコードされた画像データを保存する
Args:
image_base64: Base64エンコードされた画像データ
image_path: 保存先のパス
Returns:
bool: 保存が成功したかどうか
"""
try:
# Base64データのプレフィックスチェックと除去
if "," in image_base64:
image_base64 = image_base64.split(",")[1]
# デコードして保存
image_binary = base64.b64decode(image_base64)
with open(image_path, "wb") as f:
f.write(image_binary)
return True
except Exception as e:
print(f"画像の保存中にエラーが発生しました: {e}")
return False
def create_output_dirs(base_dir: str = "outputs") -> tuple[str, str]:
"""
出力用の一意のディレクトリを作成する
Args:
base_dir: 基本となるディレクトリ名
Returns:
tuple[str, str]: (出力ディレクトリパス, 画像ディレクトリパス)
"""
# タイムスタンプを使用してユニークなディレクトリ名を生成
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_dir = Path(base_dir) / timestamp
images_dir = output_dir / "images"
# ディレクトリを作成
os.makedirs(output_dir, exist_ok=True)
os.makedirs(images_dir, exist_ok=True)
return str(output_dir), str(images_dir)
def process_image(img_data: dict, images_dir: str) -> tuple[str, str, bool]:
"""
画像データを処理し、保存する
Args:
img_data: 画像データ(id, image_base64を含む)
images_dir: 画像保存先ディレクトリ
Returns:
tuple[str, str, bool]: (画像ID, 画像パス, 成功フラグ)
"""
img_id = img_data.id.replace(".jpeg", "")
image_filename = f"{img_id}.png"
image_path = os.path.join(images_dir, image_filename)
success = save_image(img_data.image_base64, image_path)
return img_id, image_path, success
def save_markdown(
ocr_response: OCRResponse,
base_dir: str = "outputs",
) -> None:
"""
OCRの結果をMarkdownファイルとして保存する
Args:
ocr_response: OCR処理からのレスポンス
base_dir: 出力先の基本ディレクトリ名
"""
try:
# 出力用ディレクトリの作成
output_dir, images_dir = create_output_dirs(base_dir)
output_file = os.path.join(output_dir, "output.md")
markdown_content = ""
for page in ocr_response.pages:
# 画像の処理と保存
image_mappings = {}
for img in page.images:
if img.image_base64:
img_id, img_path, success = process_image(img, images_dir)
if success:
# 相対パスを使用するように修正
relative_path = os.path.relpath(
img_path, os.path.dirname(output_file)
)
image_mappings[img.id] = (img_id, relative_path)
# マークダウンテキストの更新
page_markdown = page.markdown
for orig_id, (new_id, path) in image_mappings.items():
page_markdown = page_markdown.replace(
f"", f""
)
markdown_content += page_markdown + "\\n\\n"
# Markdownファイルの保存
with open(output_file, "w", encoding="utf-8") as f:
f.write(markdown_content)
print(f"Markdownファイルを保存しました: {output_file}")
print(f"画像ファイルは {images_dir} ディレクトリに保存されました")
except Exception as e:
print(f"Markdownファイルの生成中にエラーが発生しました: {e}")
uploaded_pdf = client.files.upload(
file={
"file_name": target_filename,
"content": open(target_filename, "rb"),
},
purpose="ocr",
)
signed_url = client.files.get_signed_url(file_id=uploaded_pdf.id)
# OCR処理の実行
ocr_response = client.ocr.process(
model="mistral-ocr-latest",
document={
"type": "document_url",
"document_url": signed_url.url,
},
include_image_base64=True, # 画像のbase64データを含めるように指定
)
# 結果を保存
save_markdown(ocr_response)
これで準備OKです!
日本語の精度を見るなら、ちゃんとした日本語文書やよく見る解説資料などを基にしたほうが良いと思っったので、消費者庁の措置命令のPDFと厚生労働省から出ている資料を使うことにしました。
- 医療法人社団スマイルスクエアに対する景品表示法に基づく措置命令について
- 2020年度 京都女子大学・リカレント教育課程 ―会社法(1)―(今回は1-11ページまでを対象にしています)
.png?w=1428&fit=max&fm=webp)
.png?w=1428&fit=max&fm=webp)
検証結果
OCR処理を実行した結果、そこそこいい感じな印象でした。いくつか例をピックアップしてみます。すべて見たい方は実際に手元で試してみるのが良いと思います!
1. やや構造が特殊な部分
テキスト部分はほぼ完璧に認識できていますね。句読点の位置も正確です。
元データの該当箇所

OCRによる認識結果

2. 表組み部分
元データの該当箇所

OCRによる認識結果

3. 通常の文章っぽい部分
元データの該当箇所

OCRによる認識結果

4. うまく構造化できそうにない部分
元データの該当箇所

OCRによる認識結果

5. 図やイラストが使用されている箇所
元データの該当箇所

OCRによる認識結果
.png?w=1428&fit=max&fm=webp)
良かった点と気になった点
良かった点
- 日本語の基本精度は高い
- 普通の文章なら大体認識できているように見えます
- 普通の文章や表程度であれば十分精度は出ている
- 画像も含めて処理できる
- テキストだけじゃなく複雑な関係式やグラフがある場合は画像として出力されて扱えるのは便利
気になった点
- 構造認識にムラがある
- 「(1)対象役務」は普通のテキストなのに「(2)対象表示」は見出し(##)として処理されるなど、一貫性がないことも
- 日本語の特殊フォントが苦手
- 「消費者庁」が「浦費者庁」になってたりします
- そこまで特殊なフォントでもないですが、少しずれると認識できないようです
- 複雑なレイアウトは苦戦
- 一般的な表であれば問題なく出力できるが、表組みが複雑だったり当然だが人間の目でも意見が少しわかりにくい構造だと出力が崩れる
まとめ
Mistral OCRは全体的に見るとかなり使えるツールだと思います。
「自己ホスティング(オンプレミス)」オプションも提供しているので、機密性の高いデータも扱うことができそうです。
Private and portable.
A comprehensive, enterprise-grade AI platform that can be deployed anywhere—on-premises, cloud, edge, devices, data centers, and more.
もちろん完璧ではないので、法律文書や医療文書など100%の精度が必要な場面では人間のチェックも必要でしょうね。特殊なフォントや複雑なレイアウトがある場合は、事前に試してみることをおすすめします。
個人的には、Google Document AIやGeminiに加えて、新たな選択肢として持っておくと便利だなと思いました。