前回までのおさらいと方針転換の背景
※本記事の一部コンテンツ(文章・画像)はAIの支援を受けて作成しています。
前回は、PDFの過去問をOCRでテキスト化する検証を行いました。高DPIに設定することで、日本語の認識精度は一定の水準に達しました。しかし、数式や図を含む設問では読み取りミスが多く、このままでは結構な量の手作業が必要となりそうな気配が漂ってきました。
OCRの精度を上げ、手作業の量を減らそうと考えていましたが、方向転換し、「OCRではなく画像のまま出題する」設計に切り替えることにしました。
今回は過去問PDF読み取りツールの設計変更に関する記事になります。
テキスト化をやめるという設計判断
OCRでのテキスト化は、ある程度の精度を期待できます。OCRに挑戦してる多くの人がいろんなアイデアを共有してネットにあげてくれていると思うので。アイデアを拾って時間をかけれて作りこめば精度も上げられると可能性は高いです。
しかし、実際に時間をかけて対応しても精度が上がったとしても、図を含む設問には根本的に対応できないのではないか!と気づきました(本当は前から気づいてたけど、考えたくなくてスルーしてた)
それであれば、まずはPDFから設問一つずつを画像で抽出するような画像の分割処理(レイアウト解析)に注力し、「最低限使えるアプリ」を早期に作ることを優先した方が、開発としては健全だと判断しました。
なぜOCR精度の追求を後回しにしたのか(詳細)
OCR精度は上げられるかもしれないが、以下のようなリスクがつきまといます:
- 精度改善にかかる時間が読めない
- 結果的に手作業修正が必要になるかもしれない
- 精度が高くても図のある設問には無力
一方で、画像分割(PDFから抽出した問題を設問事に分ける)の精度が高ければ、最悪OCRをあきらめて「すべて画像出題」で進めることも可能になります。この選択肢ができるだけでも、プロジェクトとしての見通しは格段に良くなるはずです。
手を広げすぎず、最短で成果が見える道を選ぶ。検証は最小限に、仮説ベースでまず作ってみる。
これが今回の方針転換の背景です。
実際のシステム開発作業では、「OCRの精度を上げる!」といった成果が目に見えやすいテーマに、ついつい夢中になってしまいがちです。
夢中になるうちに、本来の目的だったはずの「データ作成の自動化」や「手作業量の削減」がどこかに行ってしまい、気づけば『OCR精度の向上』それ自体が目的になっている──そんな状態に陥ることもあります。
もしかしたら、私のように「考えたくなくて、気づきをスルーしている」ケースもあるかもしれません。そして気づけばスケジュールを超過し、「大した成果もないのに時間だけが過ぎた」という悲惨な結末に…。
もくもくと作業するのは楽ですが、その先に何を目指していたかは、常に意識しておきたいところです。
設計上の問題:混在型の面倒くささと「全画像型」の現実性
方向転換による影響ももちろんあります。方向転換にあたっていくつか設計上の問題があることがわかりました。今回の方針変更で、設問データに「テキスト型」と「画像型」の2種類が存在することになります。
パターンA:テキスト型と画像型が混在(ハイブリッド型)
- 図のない設問 → OCRでテキスト化、OCRがうまくテキスト化できない場合は画像
- 図のある設問 → 画像で保持(できれば図部分とテキスト部分を分けて持ちたい)
これにより、出題処理にif分岐が必要になり、表示形式やAIへの入力形式にも影響が出てきます。
パターンB:すべての設問を画像で出題(全画像型)
いっそ全部画像にしてしまう、という方法もあります。実際に一度は検討しましたが、以下の理由から見送りました:
- データ量が多くなる
- OCRが後で使えるようになっても移行しづらい(データ構造が変化して影響が大きい)
- テキストの方が検索・扱いが楽
そのため、現時点では「テキスト型+画像型のハイブリッド構成」を基本方針としました。
設計対応:構造の統一と分岐処理の局所化
構造上の混乱を防ぐため、以下のような方針を取ります:
- 問題と選択肢に「text」と「image」の両方のフィールドを持たせる
- 出題処理では
textがあればテキスト表示、なければ画像表示(コード値で分類するものあり) - 処理の分岐はラッパー関数で抽象化して、UIやロジック側は統一
アプリ上で、同じ使用目的のデータに対してテキストと画像が混在する、という嫌な感じの設計になりますがデータ作りに時間をかけるよりは良いでしょう。何といってもデータ作り、アプリ作りがメインの目的ではなくアプリを作ってから試験対策するのが本来の目的ですから!
データ構造:RDB的設計とNoSQLとのギャップ
ざっと考えましたが、試験では過去問が多く、選択肢の順番が入れ替わったりする、とのことから以下のようなデータの持たせ方が良さそうです。現場経験からRDBで持つ構造がまず思いつきます。
試験対策アプリケーションで持つデータと構造(案)
問題 {
問題ID
問題文(nullable)
添付画像(nullable)
正解選択肢ID
タイプ(問題文がテキストなのか、画像なのか、ミックスなのか?のようなフラグ)
}
選択肢 {
選択肢ID
問題ID(外部キー)
回答文(nullable)
回答画像(nullable)
タイプ(選択肢がテキストなのか、画像なのか、ミックスなのか?のようなフラグ)
}
※ 問題、選択肢は画像が複数のケースもあるか??その場合は再検討
回答 {
開催回ID
問題ID
選択肢ID
選択肢テキスト
正解フラグ
}
開催回 {
開催回ID
年度(西暦・和暦)
春季/秋季
}
データ構造の特徴と意図
- 「回答」テーブルは問題ID×開催回ID×選択肢IDの組で構成 → 同一問題でも開催回により選択肢が変化しても対応可能
- 「問題」「選択肢」はテキストと画像を併用可 → 図入り問題やOCR不完全な選択肢もカバー
- 正規化されており、柔軟性・拡張性・出題時の一貫性がある
RDBかNoSQLか
もしかして、テキストで出題するのか、画像で出題するのか決まり切ってない場合、NoSQLの方がよいのでしょうか?とChatGPTに質問しました。
図入り/図なし・テキスト/画像といった「表現上の揺らぎ」をデータモデル上で許容する前提で設計このような正規化された設計は長年のRDB経験の延長にありますが、NoSQLで運用するなら「1問=1ドキュメント」型で選択肢や正解もネストした方が取り回しが良くなる可能性もあります。
- 最初は画像で持っていた問題でも、後からOCRの精度が改善したらテキストを追加するだけで移行可能
- テキストで扱えるデータは極力テキスト化しておき、検索性や軽量性を活かす
データ構造を考える初期段階から無意識に正規化がしみついた設計者としては、新鮮な視点でしたが、用途に応じて最適な構造を選ぶ柔軟さが重要だと感じています。RDBかNoSQLかは画像分割の検証がおわってから決めたいと思います。
今後の検証:画像分割の精度を見極める
今後は以下の技術で、設問ごとの画像分割(セグメンテーション)を検証予定です。
- OpenCV:閾値処理+輪郭抽出で矩形領域を分割
- Layout-Parser:事前学習済みモデルによる構造化検出
ここで十分な精度が得られれば、画像出題の基盤が整い、テキスト化をあきらめる「逃げ道」も確保できます。OCR精度向上と並行して、アプリの本体実装にも移行していく予定です。

