TeXベース電子採点ソフトを作ってみた
LaTeX で解答用紙を作れるようになると、次に欲しくなるのは「その答案を採点するところまで、まとめて進めたい」という仕組みでした。
解答欄を作るパッケージ KKran を元に、塾向けの電子採点ソフト Scoring64 を作りました。Windows と Mac で動くソフトで、マークシートの読み取りと正誤判定・得点計算は期間を限らず無料です。用紙作成や記述採点などの有料機能には、初回10日間のお試しを用意しています。
本当は全部無料で提供したかったのですが...。かなりの時間と多少の必要経費がかかったので、フル使用は有料という形を取らせていただくことにしました。他の電子採点システムを提供している会社様のことも考慮し、値段設定は相場に近いものとするという判断をしています。ご了承ください。
出発点の KKran は、LaTeX のコマンドだけで解答欄を組むパッケージです。次の用紙は Scoring64 を使わず、KKran と LuaLaTeX だけで組みました。マーク式・短答式・文字数指定・記述式の欄を、コマンドで並べています。
短答式の部分のソースは、次のような書き方です。欄の幅と高さを mm で指定し、\GoDown で次の行へ進みます。
\KKran[.6pt]{%
\大問番号[0]{27}[]%
\SetShoumon{0}\小問番号[8]{9}\小問欄{70}{9}%
\SetShoumon{3}\小問番号[8]{9}\小問欄{70}{9}\GoDown{9}%
\SetShoumon{1}\小問番号[8]{9}\小問欄{35}{9}[east={\fontsize{8}{9}\selectfont cm\;}]%
\小問欄{35}{9}[east={\fontsize{8}{9}\selectfont cm$^2$\;}]%
\SetShoumon{4}\小問番号[8]{9}\小問欄{70}{9}[center={\fontsize{10}{10}\selectfont\マークシート{49}{\四択マーク配列}}]\GoDown{9}%
\SetShoumon{2}\小問番号[8]{9}\小問欄{70}{9}%
\SetShoumon{5}\小問番号[8]{9}\小問欄{70}{9}%
}%
Scoring64 は、この KKran の用紙を画面から作り、そのまま採点まで進めるためのソフトです。
この記事では、解答用紙の組版から電子採点へ広げる際に考えたことと、実際の操作画面を紹介します。
現在の開始画面です。まずは、用紙を作るところから答案を返すところまでを、一つのソフトで扱う形にしています。
画面で見ると、全体は次の4場面です。用紙を作り、答案を取り込み、採点して、返却用に出力します。
着想
実は、このソフトのアイデア自体は、もうかなり前から鉄緑会内部で使われているものです。実際、自分が着想を得たのは TeXConf2025における渡辺さんのスライドでした。
当時時間が有り余っていた自分は、これをなんとかしてリリースし、一般向けソフトとして売り出そうという気概を持って開発を試みていたのですが、色々な障壁がありました。
私はかねてより、自分の好きな鉄緑会らしさを保った組版の研究に勤しんできましたが、このソフトの開発はその集大成とも言えるものであり、やっと完成に至ったことを大変喜ばしく思っています。
それでは、ほんのちょっとですが、開発の方法や裏側を覗いていってください。
障壁1 PDFの切り出し問題
KKran は、Lua と TikZ を使って試験の解答欄を組む LaTeX パッケージです。記述用の枠やマーク式の解答欄などを、ごく単純なコマンドで配置できます。要するに解答欄自体は LaTeX だけでかなり簡便に作れるようになったわけです。
ところが、解答欄を作れることと、回収した答案からその欄だけを切り出せることは、別の問題です。元の PDF ではきれいに並んでいた枠も、一度印刷して、人が書き込んでスキャンして戻ってくると、同じ位置にそのまま収まっているとは限りません。
紙が少し傾いていたり、余白の入り方が違っていたりするだけでも、切り出す範囲はずれます。枠の位置を目印にしたいのに、その枠には手書きの文字や途中式が重なります。「この辺りに解答欄があるはず」で切り出すと、肝心の解答が欠けたり、隣の問題まで入ったりするわけです。
しかも、採点する側からすると、画像が何枚か切り出せればよいという話でもありません。それが誰の答案の何問目なのか、どの配点で採点するものなのかまで対応していないと、実際には使えません。見た目がそれらしい画像でも、別の設問として表示されていたら困ります。
マークシートでは、その先に「切り出した欄のどれが塗られているか」という問題もあります。濃く塗られた答案だけなら簡単そうに見えますが、実際には薄い塗り、消し跡、二重マークなどがあります。枠や選択肢の文字も黒いので、単に黒い画素を数えれば済むわけでもありません。
つまり、解答欄の位置を合わせることと、その中の書き込みを読むことを、それぞれ考える必要がありました。
そこで、まず用紙側で解答欄の範囲と設問の対応を設定し、採点に進む前に切り出し結果を一覧で確認できるようにしました。取り込めたという表示だけで済ませず、実際にどこを切り出す設定になっているのかを見せる形です。
KKran ベースの用紙については、組版後の PDF 上での位置を取り出し、解答欄ごとにページと矩形の範囲を持たせています。TeX 側で指定した幅や高さだけでは、改ページや余白を含めて、最終的にどこへ置かれたかまでは分からないからです。
範囲が決まった後の切り出し部分だけなら、考え方は単純です。説明用に縮めると、次のようになります。
x, y, w, h = (region[k] for k in ("x", "y", "width", "height"))
box = tuple(round(v * scale) for v in (x, y, x + w, y + h))
answer_image = aligned_page.crop(box)
region は PDF 上の解答欄の範囲、scale は PDF の座標を画像のピクセルに換算する倍率です。aligned_page は位置合わせを済ませた答案画像として、ここではその処理を省いています。切り出した画像には設問との対応も持たせ、採点側で扱えるようにします。
例えば、番号や氏名の枠も用紙の中にはありますが、そこに点数を付けたいわけではありません。上の画面では、それらを「採点しない」欄として分けています。解答欄については番号と種類を確認し、範囲がおかしければ紙面に戻って直します。
切り出し処理そのものの詳しい話は省きますが、その結果を人が確認して修正できるところまでを一つの流れにしました。自動処理を通ったというだけで正しいものとして扱わず、採点に使う設定を確かめられるようにしたわけです。
切り出しの確認では、解答欄の候補が一覧になります。番号を順に振り直す操作もここから行えます。候補に出なかった欄は、「欄を手動で追加」で紙面の範囲を囲んで足します。共通テスト用マークシートも、同じ「採点の設定」の欄から確かめられます。
障壁2 TeX を知らない人向けに UI を作る
もう一つの障壁は、使う人が TeX を知っているとは限らないことでした。自分で使うだけなら、コマンドを書いて解答欄を配置し、必要な設定をソースに書き込めば済みます。しかし、一般向けのソフトとして売り出す以上、先生にまず TeX を覚えてもらうわけにはいきません。
例えば「この問題は記述式で、配点は5点、解答欄はここ」という指定を、コードを書かずにできる必要があります。TeX を使う側からすると短い記述で済むことでも、画面にすると、どこで範囲を指定するのか、何を入力するのか、間違えたらどう直すのかまで用意しなければなりません。単にコマンドの引数を入力欄に置き換えるだけでは、使う側に同じ知識を要求してしまいます。
例えば、設定名や数値をそのまま並べると、こういう画面になってしまいます。
※この画像は、使いづらい UI を説明するためにコードで作って動かした再現モックです。実際の過去バージョンの画面ではありません。
作った側には意味が分かっていても、初めて使う人からすると、どこから触ればよいのか分かりません。設定できる項目を増やすことと、使える画面を作ることは別の話でした。
そこで、位置の指定は紙面を見ながら行い、問題の種類は選択肢から選ぶ形にしました。座標の数値だけを入力してもらうより、触っている解答欄がどこにあるのか分かる方が、設定の間違いにも気付きやすいからです。
正解の指定も、記号をコードに書く代わりに、画面の「ア・イ・ウ・エ」をクリックする形にしています。配点はその横で入力します。先生が考えている「この問題の正解はイで、10点」という内容を、そのまま操作にしたわけです。
正解と配点は、「正解・配点の入力」の一覧でまとめて入力できます。記号の正解は「正解を続けて入力」で 3142 のように続けて打つこともでき、別解を認める問題は採点方式を「単答(別解あり)」にします。部分点が要る記述問題は、採点画面でテンキーから入力します。
裏側で必要になる指定はソフト側で受け持ち、使う人には問題と配点を設定してもらう。この分け方にすると、TeX の知識を前提にしていた操作を、少しずつ画面から行えるようになりました。
用紙を作る画面は、こうなっています。紙面の空白をクリックして置き場所を決め、「部品を追加」から解答欄・文字・数式・図などを置いていきます。部品はドラッグで動かせ、コピーして貼り付けたり、範囲選択でまとめて動かしたりもできます。
最新版では、この紙面を TeX の組版を待たずに手元で描くようにしました。KKran の用紙は組版のたびに待ち時間が出るので、触るたびに画面が止まっては使い物にならないからです。TeX は裏で照合と PDF の出力を受け持ち、手元の描画とずれていないかを確かめています。TeX が PC に入っていなくても、アプリの中から軽量版を用意できます。
部品は選ぶと幅・高さや番号を設定でき、複数の部品を範囲選択してまとめて動かせます。用紙の設定では用紙サイズ・余白・1マスの大きさを決め、作った用紙はテンプレートとして登録できます。
新しい試験では、最初の用紙として白紙・番号と氏名の欄付き・共通テスト用マークシート(22科目)・登録したテンプレートなどを選べます。東大編集版は、数学(文系・理系)・理科・社会の A3 の4種です。ほかに、数学と理科の練習用紙(A4・B5)もテンプレートに入っています。
実際に作れる用紙の例です。共通テスト用マークシート、東大編集版、記号と記述を組み合わせた自作用紙などを、同じ画面から作れます。
模範解答の入った用紙も出力できます。無記入版と同じ紙面に正解を重ねる形で、先生の手元用に使えます。
障壁3 TeX 以外で作られた PDF も取り込めるようにする
TeX を知らなくても操作できる画面ができたとして、取り込める用紙が TeX で作ったものだけなら、使える場面はかなり限られます。先生が普段使っているのは Word や Excel で作ったプリントかもしれませんし、紙でしか残っていない教材もあります。電子採点を始めるために、それらを全部 TeX で作り直してもらうわけにはいきません。
自分で KKran を使って作った用紙なら、どのコマンドでどの解答欄を配置したのか、ソースを見れば分かります。しかし、外から持ってきた PDF には、その前提を置けません。画面に四角い枠が表示されていても、それが解答欄なのか、問題を囲む枠なのか、単なる表の一部なのかは別の話です。さらに、解答欄だと分かっても、それが何問目で、記号式なのか記述式なのかまでは、見た目だけで決められません。
用紙の作り方も統一されていません。独立した枠もあれば、表のセルを解答欄にしたものもあります。スキャンした教材では、印刷された線も文字も画像として扱うことになります。同じ PDF という形式で開けることと、その中の解答欄を採点に使えることは、別の問題でした。
ここは、取り込んだ PDF から解答欄の候補を出す段階と、それを採点に使う欄として確認する段階を分けました。候補が出た時点で全部を確定するのではなく、先生が紙面を見ながら設定を直す形です。
例えば、記述欄なのに記号欄として候補が出た場合は種類を直し、見落とされた欄は「欄を手動で追加」で範囲を囲んで追加します。枠が見つかったことだけでは足りないので、設問の番号も合わせて確認してもらいます。
取り込んだ教材の上に、解答欄の候補を表示した画面です。紙面を見ながら、採点に使う範囲を確かめられるようにしています。
取り込みから採点までの流れは、PDF を開く、スキャンした答案を取り込む、解答欄の候補を確認する、切り出した答案を採点する、の順です。
これで、元の作成ソフトの情報がなくても、採点に必要な設定を画面から加えられるようになります。どんな用紙でも完全に自動で扱えるというところまでは行きませんが、教材を作り直す以外の始め方を用意できたわけです。
マークシートの読み取りだけ少し詳しく
ここまでの話を全部書くとかなり長くなりそうなので、今回はマークシートの読み取りのところだけ、もう少し書いてみます。この部分は無料機能として用意するので、作る時に考えたことを少し紹介します。
無料の読取では、未記入の用紙と記入済みの答案を使います。等間隔に並ぶマーク欄を対象にしていて、両方の PDF は同じ大きさ・向きにそろえる前提です。未記入の用紙は1ページ、答案は100ページまでで、それぞれ20MB まで読み込めます。キーの入力は要らず、読み取りも採点もオフラインで動きます。
読み取りの流れは、未記入の用紙と答案を読み込み、最初のマーク欄の位置を赤い枠で合わせ、得点と正誤を一覧で確認する、の順です。薄塗りや二重マークは「要確認」として別に表示します。
まず同じ欄を見ているか確かめる
最初に必要なのは、塗りを読むことよりも、ちゃんと同じ欄を見ているか確かめることでした。印刷してスキャンすると、同じ用紙でも位置が少しずれます。そのまま比較すると、枠線を鉛筆の塗りと勘違いすることがあります。
そこで、用紙にもともとある印刷を手がかりにして、位置のずれを調整してから読み取る形にしました。どこを見ているかが怪しいまま、塗りの判定だけ頑張っても仕方がないわけです。
黒い部分が全部回答とは限らない
マーク欄には、枠や選択肢の文字が最初から印刷されています。答案の黒い部分をそのまま数えると、何も書いていない用紙にも回答があるように見えてしまいます。
ここで未記入の用紙が役に立ちます。もともとの印刷と、後から加わった書き込みを区別するための材料になるからです。スキャンによって紙の明るさも変わるので、その違いも考慮しながら、塗りに相当する部分を見ていきます。
ただ、濃さが分かれば解決というわけでもありません。一番濃い欄を答えにすると、無回答の問題にも何かしら答えが付いてしまいます。薄い塗りや消し跡もあるので、濃さだけで即決せず、塗られ方も含めて判断するようにしました。このあたりは、きれいな見本を読めた後に、実際の答案で引っかかったところです。
採点と確認を分ける
もう一つ気を付けたのは、採点結果を出すことと、確認が必要かどうかを分けることです。薄い塗りや消し跡があるたびに採点を止めてしまうと、点数を見るために、先に全部の確認を済ませる必要が出てきます。
そこで、読み取りが怪しいものにも自動採点の結果を出し、その上で「要確認」を付ける形にしました。合計点も表示するので、まず答案全体の結果を見てから、気になる問題を確認できます。
図の例では、10点という採点結果と「要確認」が同時に残ります。
要確認になった欄は、答案の画像を見て先生が決めます。手書きの答案も同じように画像を見て採点でき、読み取り結果は CSV で保存できます。
コード側でも、得点と確認の状態は別々に持たせています。単答の採点部分だけに縮めると、こんな形です。実装を説明用に簡略化した例で、読み取り処理の中身は省いています。
candidate = automatic_answer(reading)
score = points if candidate == answer else 0
needs_review = reading["state"] not in ("single", "blank")
result = {"score": score, "review": needs_review}
automatic_answer は採点に使う回答候補を取り出す部分です。score と review を別にしておけば、点数を集計する処理を止めずに、確認する問題だけを拾えます。
点数が出ているからといって、読み取りまで確かだとは限りません。「何点と判定したか」と「人が確認する必要があるか」を別々に扱うことも、実際に使うためには必要だったと思います。
採点から返却まで
最後に、採点と返却の画面です。採点画面の下部には満点・0点・部分点のボタンがあり、配点が増えてもボタンは増えません。部分点は0点から配点までの整数をテンキーで入力し、Enter で確定します。答案は「1人ずつ」「一覧」「用紙全体」で見られ、「1人ずつ」では採点すると次の答案へ進みます。
採点が済んだら、生徒別の返却 PDF と得点 CSV を出力できます。未採点の問題を 0 点として出力することはありません。全試験を .scoring64 ファイルにバックアップし、あとから復元することもできます。
おわりに
今回は、電子採点ソフトを作る時に引っかかったことと、マークシートを読み取る時に考えたことを少し紹介しました。
Scoring64 のマークシート読み取り(読み取り・正誤判定・得点計算・結果 CSV の保存)は、期間を限らず無料で使えます。用紙の作成や答案の取り込み、記述答案の採点、返却まで扱う部分は、初回10日間のお試しの後に有料になります。実際の操作やダウンロードについては、案内サイトをご覧ください。
この記事は、開発者による製品紹介です。掲載した操作画面は見本データを使っています。マークシート読み取りの例には、見本用に作った答案を含みます。























