春告げ鳥

興味のあることをごちゃ混ぜで書いているので、.カテゴリー別に閲覧することをオススメします

6桁の数字を読み取りたい

この記事は、kstm Advent Calendar 13日目の記事として書かれました。 qiita.com

ある時ふと7セグメントのLCDを読み取る必要があるかもしれない。それは、デジタル電流計かもしれないし、分解してはいけないファンヒーターの温度計かもしれない。

f:id:ugwis:20181213154118j:plain

単純に考えれば、Webカメラを固定し、光源を用意し、座標を指定してOCRすればよいと考える。
しかしそのような手間はきっとソフトウェアで対処することができる

物体検出

カメラや物体の位置がずれてもカメラの中に映っていれば、認識してほしいと思う。パターンマッチングなどいろいろな方法で7セグメントLCDを読み取ることができるが、今回の場合は7セグメントLCDの周りの物体を検出し、LCDの場所を推定しようと思う。

特徴点抽出

画像のような大きいデータはできるだけその画像の特徴を表したベクトルに変換すると良い。変換することを特徴点抽出といい、SIFTやSURFなどはそれらを抽出するためのアルゴリズムである。

特徴点は多ければ良いというものではなく、後述するマッチングを行う際に特徴点に比例して計算量が増えるため、画像自体を少ない数で画像の特徴を表す特徴点を取るアルゴリズムが良い。今回はSIFT,SURFが特許の関係があるため、A-KAZE特徴量を想定する。

f:id:ugwis:20181213154122p:plain
↑小さく表示されている円が特徴点

A-KAZE特徴量抽出アルゴリズムは前身のKAZE(風)を高速化したもので、他のアルゴリズムに比べスケール変化耐性、回転耐性、輝度変化耐性、Blur耐性、スピードどれも精度がよく、またSIFTやSURFは特許の問題があるため代用としてAKAZEがよく使われています。

SIFT,SURF,ORBなど他のアルゴリズムと精度を比較した記事があります。
AKAZE特徴量の紹介と他特徴量との比較

特徴点マッチング

Webカメラを固定せずに7セグメントを読み取るためには画像の中に物体がどこにあるかを判定する必要がある。あらかじめ物体の写真を撮って、Webカメラから送られてくる画像と特徴点マッチングを行うと、物体がどこに映っているのかを見つけることができる。

f:id:ugwis:20181213154141p:plain

二つの画像の特徴点をそれぞれどの点なのか対を生成する(マッチング)ことにより、画像のスケール、傾き、反転などに影響されることなく物体を検出することができる。

特徴点マッチングのアルゴリズムは総当たり(ブルートフォース)、高速最近傍探索(FLANN)などがあり計算量は違うが、なににせよ前述した特徴点が少なく効率よく特徴を表しているほど射影変換がうまく行く。

射影変換

特徴点マッチングを終えたあとは、ホモグラフィ変換(射影変換)により対象とする物体が画像のどこにあるかを変換する。
画像は変換したあと、物体があると認識されている部分を矩形で表示している。

f:id:ugwis:20181213154125p:plain

OpenCVチュートリアル - 画像の幾何変換

7-segの読み取り

矩形検出

物体の位置がわかったため、物体の中のLCDの位置を矩形検出する。
LCDはほぼ長方形の形をしていることが多いため、findContours()で輪郭を検出することでLCDの場所を見つけることができる。

f:id:ugwis:20181213154218p:plain

ヒストグラム平坦化

ここまでで、LCDの位置や傾きなどの問題に対処することができたが、輝度の問題が解消できない。光源が変わってもある程度読み取るためには光源が変わっても輝度値が大きく変化しないようにすることが重要である。

ヒストグラム平坦化
引用: OpenCVチュートリアル - ヒストグラム その2: ヒストグラム平坦化

二値化

LCDで背景の部分と数字が表示されている部分をくっきりと分けるほどOCRの精度が上がる。背景を白、文字を黒と二つの色だけに分けるのを二値化と呼ぶ。二値化するときに問題なのは、単純な閾値だけで分ける場合閾値を指定しなければいけない、光源によって全体的にグラデーションのかかった画像はうまく二値化することができない。
局所的な二値化を適応閾値(Adaptive Theshold)で行うことで全体的なグラデーションによらずうまく二値化することができる
f:id:ugwis:20181213154200p:plain

クロージング処理

二値化だけではセグメントの周囲にごま塩ノイズができるため、これがOCRの認識の邪魔をしていた。
クロージング処理は膨張した後に縮小処理をすることによって画像内の小さな黒い点を除去できる
OpenCVではmorphologyExcv2.MORPH_CLOSEを指定することによってクロージング処理ができる
処理前
f:id:ugwis:20181213154200p:plain
処理後
f:id:ugwis:20181213154138p:plain
モルフォロジー変換

SSOCR

LCD部分を適応閾値により二値化し、OCRで数字を認識する。TesseractなどいろんなOCRがあるが、今回のように7-segのみを読み取る場合はssocr(Seven Segment Optical Character Recognition)がオススメである。

f:id:ugwis:20181213154211p:plain

https://www.unix-ag.uni-kl.de/~auerswal/ssocr/

参考文献

「特徴点のマッチングとHomographyによる物体検出」
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html

「Fast Explicit Diffusion for Accelerated Features in Nonlinear Scale Spaces」 http://www.bmva.org/bmvc/2013/Papers/paper0013/paper0013.pdf