前回の「冬休みの自由研究でOCRを作ってみた」では、最後の認識にMNISTを学習データとして使ったので、あまり精度が良くなかった。そこで、認識の部分にOSSのOCRであるtesseractを使用することで、再度検証してみることにした。tesseractには、-psmというパラメータで認識方法を指定できる。
Page segmentation modes:
0 Orientation and script detection (OSD) only.
1 Automatic page segmentation with OSD.
2 Automatic page segmentation, but no OSD, or OCR.
3 Fully automatic page segmentation, but no OSD. (Default)
4 Assume a single column of text of variable sizes.
5 Assume a single uniform block of vertically aligned text.
6 Assume a single uniform block of text.
7 Treat the image as a single text line.
8 Treat the image as a single word.
9 Treat the image as a single word in a circle.
10 Treat the image as a single character.
10を指定すれば、1つの文字として認識を行うことができる。もちろん、tesseractがあるなら、そのままOCRとして使えばいいわけで実用性あるの? という話になるが、tesseractは、特定の苦手なシーンがあり、今回の方法でそれが克服できないかを検証することが目的だ。合わせて、手軽に使えるOCRの中では個人的には一番精度が高いと評価している、Google Cloud Visionとの比較もしてみることにする。Google Cloud Visionは、このサイトで簡単に試してみることが可能だ。
今回は、こういう画像を使用。tesseractは二値化されていないと精度が著しく落ちるので、予め二値化してある。
Google Cloud Vision使ってみると、きちんと認識されている。さすがだ。
今回のOCRは数字が等幅フォントで1行で書かれたものを処理対象とするため、ここから切り出してから処理する。
まずは、普通に切り出したものを処理してみる。tesseractというオプション指定を追加して、分解した文字をtesseract -psm 10で1文字ずつ認識するようにしてみた。
$ docker run -it --rm -v /tmp:/tmp ruimo/lightocr tesseract /tmp/form000.png
3.14159265
正しく認識されている。もっともこれは、tesseractで-psm 7を指定しても正しく認識できる。
$ tesseract form000.png stdout -psm 7 digits
3.14159265
Google Cloud Visionでもok。
お次は、イメージ切り抜きの際にズレて右側の罫線が入ってしまったケース。
普通にtesseractで認識してみる。
$ tesseract form001.png stdout -psm 7 digits
3.141592651
罫線部分が1と認識されてしまう。無理もない。今回のOCRで処理してみる。
$ docker run -it --rm -v /tmp:/tmp ruimo/lightocr tesseract /tmp/form001.png
3.14159265
等幅フォントを仮定して切り離した後に、幅が極端に小さなものは捨てるためきちんと認識できている。Google Cloud Visionだと、正しく認識できている。さすがだ。
次は罫線がもっと数字に寄ってしまったケース。
普通にtesseractで認識すると、
$ tesseract form003.png stdout -psm 7 digits
3.14159263
最後の5が3と誤認識されていることが分かる。今回のOCRを使うと、
$ docker run -it --rm -v /tmp:/tmp ruimo/lightocr tesseract /tmp/form003.png
3.14159265
正しく認識できた。等幅フォントを仮定して切り取るため、罫線がうまく削除できたのだと思われる。Google Cloud Visionだと、
やはり正しく認識できていてさすがだ。次は下に罫線が残ってしまったケース。
普通にtesseractを使うと、
$ tesseract form004.png stdout -psm 7 digits
1 0 .
全然ダメになってしまった。今回のOCRだと、
$ docker run -it --rm -v /tmp:/tmp ruimo/lightocr tesseract /tmp/form004.png
3 11159255
幾分改善するが、やはり誤読が見られる。もっとも横方向の罫線については、黒成分が極端に高いものを除外することで、除去できるかもしれない。Google Cloud Visionだと、
やはりきちんと認識されている。ここまではGoogle Cloud Visionの圧勝だ。次に印字が不鮮明なケースを検証してみる。ドット・インパクト・プリンタの場合、良く一部が不鮮明になるケースがある。これは6の下部が消えてしまった例。
tesseractで認識してみる。
$ tesseract form005.png stdout -psm 7 digits
3.14159255
誤読してしまっている。今回のOCRでは、
$ docker run -it --rm -v /tmp:/tmp ruimo/lightocr tesseract /tmp/form005.png
3.14159265
正しく認識された。1文字として認識する場合には精度が上がるようだ。Google Cloud Visionでは、
やはり圧倒的な強さを見せつけている。最後に全体にもっと不鮮明な上に罫線がカブっているケースを見てみる。
tesseractで普通に認識すると、
$ tesseract form006.png stdout -psm 7 digits
70001393652
最後の2桁を誤読しているが、左の罫線による悪影響は出ていなかった。今回のOCRを試してみる。
$ docker run -it --rm -v /tmp:/tmp ruimo/lightocr tesseract /tmp/form006.png
7000139369
正しく認識できた。Google Cloud Visionでは、
Google先生、全勝はならず。tesseractは、ホワイト・リストで「数字しかない」という情報を与えることができる(引数のdigits)が、Google Cloud Visionはそういう指定が無く、言語の指定しかできないので印字が不鮮明な場合は、tesseractの方が良い結果が得られる場合もあるようだ。
というわけで、割と良い結果が得られたので満足。