るいもの戯れ言
#771
2019/01/19 09:30

前回の「冬休みの自由研究で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の方が良い結果が得られる場合もあるようだ。

というわけで、割と良い結果が得られたので満足。