2013年1月30日水曜日

OpenCVで検出結果を楕円にあわせる


FloodFillなどの処理により、マスク画像を取得した後に、大まかな領域情報を得る手法の一つとして、検出領域を四角形で囲い込む内容を前に投稿した

今度は、検出結果を、四角ではなく、cv::fitEllipseを使用して楕円にあわせる

前回同様に、cv::RotatedRecが戻り値であるが、楕円の場合は、cv::ellipseで表示できる

cv::RotatedRect rRect =  cv::fitEllipse(polygon);
cv::ellipse(image, rRect, cv::Scalar(0,255,0));

cv::RotatedRectには、中心と、サイズと、傾きが格納されているため、楕円を描画することはできるが、RotatedRectという名称にはしっくりこない

OpenCVで傾いた矩形を描画する


FloodFillなどの処理により、マスク画像を取得した後に、大まかな領域情報を得る手法の一つとして、cv::findContoursで輪郭線を検出し、さらにcv::minAreaRectで全体を囲んだ四角形(傾きあり)を使用することがある。

ただし、cv::minAreaRectの戻り値が、cv::RotatedRectであるため、cv::rectangleでは、描画できない。

そのため、cv::RotatedRectから、4点を取り出し、自分で4つの線を描画する必要がある

cv::RotatedRect rRect =  cv::minAreaRect(polygon);

cv::Point2f vertices[4];
rRect.points(vertices);
for (int i = 0; i < 4; i++)
line(image, vertices[i], vertices[(i+1)%4], cv::Scalar(0,255,0));

説明はここ

OpenCV for Androidのtutorial 3を試してみた


OpenCVに慣れてきたのでPCだけでなく、Android版を試してみた。

今回は、tutorialの3で、NDKROOTの設定ができており、eclipseの起動のみ注意すれば、eclipseにsampleをimportするだけで良い。

tutorialの3では、AndroidのJNIの仕組みを利用して、Native側で特徴点の検出と描画を行う

JAVA側
データの入力は、前回と同じ、public Mat onCameraFrame(Mat inputFrame) {
の部分で受け取り、入力画像を一旦コピーし、白黒に変換

その後、自分で定義した
public native void FindFeatures(long matAddrGr, long matAddrRgba);
に、白黒画像のMatと、結果を受け取るMatの内部データのポインタを引き渡す

Matからポインタを取得するには、.getNativeObjAddr()を使用する

Native側
プロジェクトのJNIフォルダーのjni_part.cppにあたる

JAVA側とのインタフェースを宣言し
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial3_Sample3Native_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

関数の中では、JAVA側から渡されたMatのポインタをMatにCastして受け取っている
Mat& mGr  = *(Mat*)addrGray;

その後は、通常のC++のコードで検出した特徴点のキーポイントのベクターからキーポイントを取り出し、円を描画している

このサンプルをまねすれば、簡単にC++で自作の処理を行わすことができそうだ

2013年1月29日火曜日

OpenCVによる画像の膨張と縮小


FloodFillなどの処理により、マスク画像を取得した後、ノイズ除去や欠落部分の補完に、モルフォロジー演算を行う

よく使用するのは、
画像のノイズやひげを除去する 
cv::erode(from, to, cv::Mat(), cv::Point(-1,-1), 1);

画像の欠損部を補完する
cv::dilate(from, to, cv::Mat(), cv::Point(-1,-1), 1);
がある。

cv::Mat()を指定するとデフォルトのサイズ3x3が選択される

それ以外のサイズを用いる場合には
cv::Mat element(5,5,CV_8U, cv::Scalar(1))などで、エレメントを指定する

サイズは正方形ではなく、長方形にすれば、縦方向のエッジのみ接続するなどできる

この手法は、Mastering OpenCV with Practical Computer Vision Project chap. 5でナンバープレート検出に使用されている

それぞれ、最後のパラメータは適用する回数であり、複数化適用することによりセグメントの分離や結合することができる

ただし、それぞれ1回演算を行うと、サイズが縮小、あるいは拡大するので、サイズを維持する場合には、反対の処理を行う必要がある


OpenCVでは、利便性を考え、複数を処理を行う morphologyEx 関数も準備されいる。

cv::morphologyEx(from, to, op, cv::Mat(), cv::Point(-1,-1), 1)

3番目のパラメータは、処理であり、
MORPH_OPEN オープニング
MORPH_CLOSE クロージング
など指定する


参考
詳解 OpenCVの 5.3の画像のモルフォロジー P119
OpenCV 2 Computer Vision Application Programming Cookbook Chap.5 P117

2013年1月28日月曜日

OpenCV for AndroidのAPIリファレンスに関して

The OpenCV Manager Manualは、OpenCV for AndroidのSDKの中に、pdfファイルとして含まれており、最初の数ページに、基本的な使用方法が記載されている

しかし、APIのリファレンスは、pdfに記載されていなく、pdfのリンクからWebページにアクセスすることになる

Androidの開発経験があれば、問題ないかと思われる。

OpenCVでVideoCaptureに関して


OpenCVの画像の入出力は、ffmegを使用しており、OpenCVでは、ffmpeg用のパラメータの設定と、cv::Matとのフォーマット変換を行っているようである。

前述のDIBの問題を調べるために、ソースを少し覗いてみた。
関連部分のソースは、modules\highgui\srcのcap_ffmpeg_impl.hppにあたる

補足
以前 VideoCaptureの対応フォーマットに関してメモを書いたが、対応しているフォーマットは、上記ソースを見るとFOURCCと対応して、const AVCodecTag codec_bmp_tags[]に列挙されている

この部分は、ffmpeg/libavformatのriff.cから移したとのこと

OpenCVでDIBフォーマットの白黒動画像が読み込めない


DIBの白黒形式で動画を保存したファイルを、別のプログラムで読み込むとすべての値が0になるという現象に遭遇した。

画像処理の中間段階の画像を無圧縮のDIBフォーマットでファイルに保存しているのは、別のプログラムでその後の処理方式を比較するためである。

読み込まれたmatのchannelプロパティを調べると3になっており、ファイルが白黒1chと認識されていないことがわかった。

中間段階の白黒画像を、DIBのカラー形式で保存すれば、問題ないことを確認したが、サイズが3倍になってしまう。

VideoCaptureのマニュアルを見てみたが、openする場合のフォーマット指定ができないようなので、素直にカラー形式で保存することにする