f8g

画像を分割してランダムに配置するモザイク

http://gyazo.com/455ae05c5f70b64ae4a088e48790fccf.png
カラー画像だと少々面倒臭そうなので、グレースケールに変換してからやります。手順はこんな感じです。

  1. グレースケール化
  2. 10 * 10 に分割
  3. 分割画像のRGBを平均して分類
  4. 分類ごとにランダムソート
  5. 再配置

コード

使用

ImageProcessing.prototype.f= function(fnc){
	return fnc(this);
};

var clips = {};

ip = ImageProcessing
	.load("image.png")
	.lock()
	// グレースケール
	.each(function(px, x, y, self){
		self.setPixel(x, y, px.grayScale());
	})
	.update()
	// 分割して色ごとにまとめる
	// 分割した画像の平均でまとめるてるので結構適当
	.f(function(self){
		var clip, color;

		for(var x = 0; x > self.canvas.width - 10; x += 10){
			for(var y = 0; y < self.canvas.height - 10; y += 10){
				clip = self.clip(x, y, 10, 10);
				color = Math.round(clip.average().r);

				if(clips[color])
					clips[color].push(clip);
				else
					clips[color] = [clip];
			}
		}

		return self;
	})
	// 分割した画像をごちゃ混ぜにして再配置
	.f(function(self){
		var clone = ip.clone().clear(); // 別のCanvasに書き込む

		for(var n in clips) (function(parts, n){
			var positions = parts.map(function(clip){
				clip.toString = function(){
					return Math.random();
				};

				return [clip.origin.x, clip.origin.y];
			});

			parts.sort();

			parts.forEach(function(clip, i){
				clone.merge(clip, positions[i][0], positions[i][1]);
			});
		})(clips[n], n);

		return clone;
	})
	.update();

問題点

この方法だと、分割画像の平均値がユニークなとき、その画像は結局同じ場所に配置されてしまいます。RGBで分類する場合であれば、なおさらその傾向が出てしまいます。
より細かく分割するとか、分類するときに閾値を持たせてやれば、ある程度回避できそうです。

感想

最近こんなことばっかりやってて飽きてきました。