トップ絵変更

絵を描いてみたのでトップ絵更新。下段は先輩が学会で言っていてかっこよかった台詞。

画像処理を扱い始めてから、フォトショップでフィルタ処理を多用した時の罪悪感が減った気がする笑。中で何やってるかわかるようになったから。思わぬ副作用だなー笑笑
しかし絵を描く上で、フィルタ多用は悪…!



ちなみに壁紙のアップロードに結構てこずった・・・。同じ拡張子である限り何回アップロードしても変化なし。一度ログアウトしてみてもだめ。なんじゃこりゃ

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マッチング

前回書いたリアルタイム特徴点抽出&マッチング絡みですが、SURFを使って実装してる方がいらっしゃいました。


http://happymeme.com/?p=84
http://mosapui.blog116.fc2.com/blog-entry-33.html


研究室の同期もSURFを使ってやってるんですが、やっぱり早いんでしょうかね?論文読んでみようかな。

そういやこないだビデオカードでSIFTを見つけるSiftGPUを試してみたところ、2枚のマッチングで10fpsくらい。他の処理もしようとすればちときついか。
まぁ正確さはSIFTに譲るものの、実用を考えれば出来の良いSURFが10点もあれば十分なのかなー