OpenCVでドロネー三角形メモ
ドロネー三角形(delaunay triangulation)という有名らしい幾何アルゴリズムがあって、画像処理で使われる時の文脈で話せば、与えられた点群に対してそれぞれをいい具合に結ぶ辺を返す。
で、素晴らしいことにOpenCVで実装されてる。http://opencv.jp/opencv-1.0.0/document/opencvref_cv_subdivisions.html
詳しい使い方は"OpenCV\samples\c\delaunay.c"参照。。
ただ、サンプルプログラムのような単純な描画処理では何の問題もないのですが、もともと通し番号のついた点群等を持っていて、これらの隣接関係を整理したいとき等は、ドロネー関数に座標値しか渡せないので不便。(当然アルゴリズム適用後には座標値しか戻ってこず、元の点群との対応を取るのが面倒。)
そこで、関数に渡した直後に、関数内部で保有する点に改めて通し番号を付けるとOKとのこと。
ドロネー関数用の点の構造体CvSubdiv2DPointにはflagsというint型の変数があるのでこれを利用します。
こんなかんじ
CvSubdiv2DPoint *p=0; CvSubdiv2DEdge e0=0; cvSubdiv2DLocate(subdiv, fp, &e0); p = cvSubdivDelaunay2DInsert(subdiv, fp); // 追加された点へのポインタを返してくれる p->flags = newindex; // ここで新たな通し番号を付ける(例えば元の点群でのそれ)
するとあとでまた取り出せる。
ほへー。めもめも。
Adobe CS2 @ windows7 64bit
ちょっと前の話、アドビCS2をウィンドウズ7の64ビットに入れようとしたら、インストールまではうまくいく。が、起動しても認証?が通らない事態に。
インストール場所を"c:\Program Files"⇒"c:\Adobe"に変えれば桶。(スペースが邪魔なの?)
さんこー
http://www.itmedia.co.jp/help/tips/windows/w0140.html
http://dispo.se/2009/06/02/adobe-creative-suite-2-and-windows-7-64bit/
http://onair.jp/blog/2010/02/adobe-cs2-windows-7-64bit.html
OpticalFlowの結果出力にHLS2RGB
IplImageに整数を出し入れする際数字化けするので、いろいろ検索してたらこんな記事が。
http://d.hatena.ne.jp/blono/20081011/1223734332
参考にさせてもらいました。プロフィール見たら…え?10代なのこの方。
で、SURF使ってみたいと言いながら、最近はオプティカルフローを求める毎日です。オプティカルフローは動画中の各ピクセルが次のフレームでどこに移動したか(Flow)を計算する話。
なかなか良い結果が出ないんですが、そもそも画像処理の結果は息もつかせぬ数値のオラオララッシュであることが多いので、結果の善し悪しすらわからない始末。
ので、
速度ベクトルのx軸と為す角度 → 色相
速度の大きさ → 輝度
と可視化するプログラム作りました。なお、簡単のため彩度は常にmax。メモ
IplImage *VisualizeFlow(IplImage *flow) { int i, j; int a, b; float dst, dst_max=0.0; float rad, PI = 4.0*atan(1.0); int w = flow->width; int h = flow->height; IplImage *src = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3); IplImage *ret = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3); for(j=0; j<h; j++){ for(i=0; i<w; i++){ a = cvImageElem<IPL_DEPTH_32S>(flow, i, j, 0); b = cvImageElem<IPL_DEPTH_32S>(flow, i, j, 1); dst = sqrt((float)(a*a + b*b)); if(dst>dst_max) dst_max = dst; } } for(j=0; j<h; j++){ for(i=0; i<w; i++){ a = cvImageElem<IPL_DEPTH_32S>(flow, i, j, 0); b = cvImageElem<IPL_DEPTH_32S>(flow, i, j, 1); dst = sqrt((float)(a*a + b*b)); if(a==0){ if(b>=0) rad = PI / 2.0; else rad = PI * (3.0/2.0); }else{ rad = atan((float)b/(float)a); if(a<0) rad += PI; else if(rad<0) rad += 2.0 * PI; } cvImageElem<IPL_DEPTH_8U>(src, i, j, 0) = 255; // S(0-255) cvImageElem<IPL_DEPTH_8U>(src, i, j, 1) = cvRound(127.0*dst / dst_max); // L(0-255) cvImageElem<IPL_DEPTH_8U>(src, i, j, 2) = cvRound(rad * (90.0/PI)); // H(0-180) } } cvCvtColor(src, ret, CV_HLS2BGR); // HLS→RGB cvReleaseImage(&src); return ret; }
去年は自分でHSV→RGBのプログラム書いたんだけど、OpenCVに色空間変換の関数があるので使ってみた。便利便利。一括変換しかできないけどね。
Depth8Uのとき色相だけ0-180の範囲で入力する必要があることを強くメモ。
そういえば、上のプログラムではフローの大きさの最大値を初めに求め、それを使って再度全ピクセル走査して輝度を決定してる。だから前ピクセルを2回も見てるんだけど、これってなんとかならんのかな。2度手間なのではと考えてしまう。ほかの画像処理で輝度の平均やら分散求める時も悩むことなんだけど。
IplImage *flowに中心からの相対座標を入れておくと、結果はこんなかんじ。
ちなみにこの変換処理をフローの推定失敗結果に使うと、エレクトリックパレードみたいになる笑
全然スムースが効いてないorz
SURF
日本語説明
http://storage.osdev.info/pub/idmjt/diaryimage/0901/neta090130l1.pdf
英論文もpdfがありますね。
個人的にはこの手のプログラムの特許はどうなってんのか知りたい。。
SURFマッチング
前回書いたリアルタイム特徴点抽出&マッチング絡みですが、SURFを使って実装してる方がいらっしゃいました。
http://happymeme.com/?p=84
http://mosapui.blog116.fc2.com/blog-entry-33.html
研究室の同期もSURFを使ってやってるんですが、やっぱり早いんでしょうかね?論文読んでみようかな。
そういやこないだビデオカードでSIFTを見つけるSiftGPUを試してみたところ、2枚のマッチングで10fpsくらい。他の処理もしようとすればちときついか。
まぁ正確さはSIFTに譲るものの、実用を考えれば出来の良いSURFが10点もあれば十分なのかなー