【Androidアプリ開発】OpenCVでBitmapから四角形を画像認識するサンプル
この記事では、Androidアプリ開発において、Bitmap形式画像から四角形を画像認識し、その4点の座標数値を抽出する手法を説明します。
今回はサンプルとして、次の画像から付箋紙4枚の座標を抽出します。
今回の手法はあくまで一例ですが、Androidアプリ【付箋カメラ】では、実際にこの手法により写真から付箋紙を抽出してます。
前準備
Androidアプリで画像認識を行うにはOpenCVライブラリを使用すると便利です。
以下のサイトを参考にすると、簡単にOpenCVライブラリをインポートできました。
OpenCV for AndroidをAndroid Studioに導入するメモ - Qiita
ソースコード
サンプルソースコードは以下の通りです。
説明
処理としては、大きく以下の3段階となります。
①:画像読み込み
②:画像を二値化
③:輪郭の座標を取得
今回は、ソースコード中の以下の関数の処理について説明します。
・onImageScan()
・getThreshold()
輪郭抽出の核となる以下の関数に関しては、また別の記事で説明する予定です。
・getContour()
①:画像読み込み
Bitmap画像を読み込みます。
今回のサンプルでは、リソースから取得するようにしていますが、カメラやストレージ上から取得しても構いません。
Bitmap画像を読み込んだ後は、OpenCVで扱えるようにMat形式に変換します。
②:画像を二値化
画像を二値化します。
ただし、写真画像を普通に二値化すると、次の結果のようにノイズが載ってしまいます。
そこで今回の手法では、色空間をチャネル(RGBなど)に分離し、それぞれのチャネルに対して二値化を行っていきます。
ちなみに、使用するチャネルを絞ることで、特定の色のみを抽出することも可能となります。
②-1-1:RGB空間チャネルの取得
画像をRGB空間の3チャネルに分離します。
②-1-2:RGB空間 → グレースケール変換 → 二値化
RGB空間の3チャネルと、元の画像のグレースケールの差分を算出し、それぞれのチャネル値を強調します。
そして、その結果を二値化画像に変換します。
②-1-3:RGBの輪郭を取得
RGB空間の3チャネルの二値化画像から四角形の座標を抽出します。
②-2-1:YUV空間チャネルの取得
②-2-2:YUV空間 → グレースケール変換 → 二値化
②-2-3:YUVの輪郭を取得
RGB空間に実施した処理をYUV空間にも実施します。
必須ではありませんが、いろいろな色空間のチャネルを二値化することによって、輪郭抽出の精度を上げる効果がります。
他の色空間も使用すると、精度が上がる見込みですが、過剰認識(誤抽出)や処理の高負荷の原因にもなりますので、ご注意を。
②-3:マスク画像に輪郭を合成
各チャネルで抽出した座標データを使用し、抽出した四角形を黒地に白で塗り潰し、1つの二値画像に合成します。
この時点での二値化画像を表示すると、次のようになります。
「②:画像を二値化」で示した純粋な二値化と比べると、明らかに精度が上がってます。
③:輪郭の座標を取得
合成した画像から最終的な座標を抽出します。
抽出結果は、以下の通りです。4つの四角形の頂点座標(x, y)が抽出できています。
まとめ
今回は、OpenCVを使用してBitmapから四角形の4点座標を抽出する手法を取り上げました。
この4点座標データは、様々な処理に活用することができます。
例えば、Canvasを使って4点をラインで結ぶと次のようになります。
更に、原画像と合成させます。
原画像の付箋紙4枚の位置とピッタリ一致していることが分かります。
今後は、これらの表示方法やタッチ操作による頂点編集の手法などについても取り上げていきたいと思います。