Hatena::ブログ(Diary)

ますぽんの雑記

2008-11-30

Poisson Image Editing

f:id:mscp:20091227211543j:image


Poisson Image Editing は Siggraph 2003 で発表された画像合成手法の論文です。


http://research.microsoft.com/vision/cambridge/papers/perez_siggraph03.pdf


http://portal.acm.org/citation.cfm?id=882269


実際に実装して検証しました。実はこれ、一見難しそうだけど実装は凄く簡単です。論文の中にはたくさん数式がありますが、実装するのに必要なのは (7) 番目と (11) (12) だけです。これ、そのまま解こうとするとドでかい行列を Ax=b の形に持っていって反復法で解くことを想像するのですが、よく見てみると左辺第二項を右辺に移項してやって、両辺を | Np | で割ってやるとそのままガウス・ザイデル法の解法に持っていくことが出来ます。結果的にとても短いコードで実装出来ます。私の場合こんな感じになりました。iterate() を true が返るまで呼んでやると奇麗に合成されます。


bool PoissonEdit::iterate()
{
	float error = 0.0f;
	float absv = 0.0f;
	//全てのピクセルにおいて
	for( vector<pixel *>::iterator iter=pixels.begin(); iter<pixels.end(); iter++ )
	{
		pixel& pix = **iter;
		for( int i=0; i < 3; i++ ) //RGB
		{
			float sum_n = 0.0f;
			float sum_vq = 0.0f;
			for( vector<pixel *>::iterator iter2=pix.neighbors.begin(); iter2<pix.neighbors.end(); iter2++ )
				sum_n += dest[3*X((*iter2)->x,(*iter2)->y)+i];
			for( vector<pixel *>::iterator iter2=pix.neighbors.begin(); iter2<pix.neighbors.end(); iter2++ )
				sum_vq += source[3*X(pix.x,pix.y)+i]-source[3*X((*iter2)->x,(*iter2)->y)+i];
			float newValue = (1.0f/pix.neighbors.size())*( sum_n + sum_vq );
			error+=fabs(newValue-dest[3*X(pix.x,pix.y)+i]);
			absv+=fabs(newValue);
			dest[3*X(pix.x,pix.y)+i] = newValue;
		}
	}
	return error/absv < EPS;
}

ここで、pixels に入っているのは領域内にあるピクセルで neighbors はそのピクセルの縦横の4方向のお隣のピクセルです。論文では境界付近と領域の内側のピクセルで記述が若干異なりますが、実装では全然気にしなくていいんですね。


参考文献:


http://www-users.cs.umn.edu/~jchen/showcase/poisson_image_editing.pdf

http://www.cs.ucf.edu/courses/cap6412/2003/Poisson%20Image%20Editing.pdf

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証