【Androidアプリ開発】OpenCVで画像から四角形を抽出するコツ
上記の記事では、Bitmap形式画像から四角形を認識し、その4点の座標数値を抽出する手法を説明しました。
今回の記事では、画像から四角形を抽出するコツを説明します。
今回のコツを取り入れることで、次の結果のように、綺麗に四角形を抽出できるようになります。
今回も、Androidアプリ【付箋カメラ】で使用している、実際の手法となります。
前準備
割愛します。(下記参照)
【Androidアプリ開発】OpenCVでBitmapから四角形を抽出するサンプル - null product's blog
ソースコード
割愛します。(下記参照)
【Androidアプリ開発】OpenCVでBitmapから四角形を抽出するサンプル - null product's blog
説明
今回は、ソースコード中の以下の関数の処理について説明します。
・getContour()
輪郭抽出の核となる関数です。
サンプルのソースコードでは、各チャネルに分離した二値画像と、最終的に合成した二値画像に対してこの関数を実行し、それぞれの輪郭情報を抽出していきます。
/* 二値画像中の輪郭を検出 */ Listtmp_contours = new ArrayList (); Mat hierarchy = Mat.zeros(new Size(5, 5), CvType.CV_8UC1); Imgproc.findContours(mat, tmp_contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);
関数の引数となる二値画像データ(mat)から輪郭情報を抽出します。
輪郭の抽出には、OpenCVライブラリの「Imgproc.findContours()」関数を使用します。
if (Imgproc.contourArea(tmp_contours.get(i)) < mat.size().area() / (100 * 1)) { /* サイズが小さいエリアは無視 */ continue; }
輪郭のサイズが小さいエリアは無視することで、ノイズとなるデータを破棄します。
輪郭のサイズを取得するには、OpenCVライブラリの「Imgproc.contourArea()」関数を使用します。
上記の「100 * 1」は調整値なので、それぞれのアプリで変更すると良いでしょう。
上記を実施しない場合は、次の結果のようにノイズが残った状態となります。
/* 輪郭線の周囲長を取得 */ double arclen = Imgproc.arcLength(ptmat2, true); /* 直線近似 */ Imgproc.approxPolyDP(ptmat2, approx, 0.02 * arclen, true);
輪郭データの凸凹を無くす(頂点数を減らす)為に、OpenCVライブラリの「Imgproc.approxPolyDP()」関数を使用します。
また、近似精度として輪郭の周囲長を使用する為に、「Imgproc.arcLength()」関数を使用します。
なお、「0.02」は調整値なので、それぞれのアプリで変更すると良いでしょう。
if (approxf1.size().area() != 4) { /* 四角形以外は無視 */ continue; }
四角形(頂点数が4)以外のデータを無視するようにします。
上記を実施しない場合は、次の結果のように四角形以外のデータまで抽出してしまいます。
もし、四角形以外の輪郭を抽出したい場合は、「!= 4」部分を変更すると良いでしょう。
/* 輪郭情報を登録 */ contour.add(approxf1);
最後に、戻り値用の配列データに輪郭情報を登録します。