f8g

ラベリング

http://www.microsoft.com/japan/msdn/academic/Articles/Algorithm/03/
http://gyazo.com/dabfdc4e6cc224cbeec343c9c428a804.png
これ使用

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

var ip = ImageProcessing.load("img.png");

// ImageDataを使用した方が速い
ip.support.pixel = false;
ip.initPixelControl();

var labels = [];
var fil    = 0; // ラベリングする色

ip.lock()
	// 閾値処理
	.f(function(self){
		var t = self.average().average();
		//var t = (self.max().max() - self.min().min()) / 2; // 中央値

		return self.each(function(px, x, y){
			var c = px.average();
			px = new ImageProcessing.Color(c, c, c);
			self.setPixel(x, y, px.threshold(t));
		});
	})
	// ラベリング (4近傍)
	.f(function(self){
		var labelN  = 1; // label number
		var w = self.canvas.width;
		var h = self.canvas.height;

		for(var x = 0; x < w + 1; x++)
			labels.push([]);

		var setLabel = function(x, y, num){
			if(0 > x || x >= w || 0 > y || y >= h || typeof labels[x][y] != "undefined")
				return;

			// 4近傍
			var nb = [
				[x + 1, y    , num],
				[x - 1, y    , num],
				[x    , y - 1, num],
				[x    , y + 1, num]
			];

			// 4近傍をチェック
			if(self.getPixel(x, y).r == fil){
				labels[x][y] = num;

				nb.forEach(function(args){
					setLabel.apply(null, args);
				});

			}
			else
				labels[x][y] = 0;
		};

		return self.each(function(px, x, y){
			if(px.r != fil)
				labels[x][y] = 0;
			else
				setLabel(x, y, labelN++);
		});
	})
	// ラベルの番号が何故か変なので直す
	.f(function(self){
		var labelN = 1;
		var labelNs = [];

		labels.forEach(function(_, x){
			_.forEach(function(v, y){
				if(v > 0 && !labelNs[v])
					labelNs[v] = labelN++;
				labels[x][y] = labelNs[v];
			})
		})

		return self;
	})
	// 表示
	.f(function(self){
		var colors = [
			ImageProcessing.Color.fromHex(0xff0000),
			ImageProcessing.Color.fromHex(0x00ff00),
			ImageProcessing.Color.fromHex(0x0000ff),
			ImageProcessing.Color.fromHex(0xffcc00),
			ImageProcessing.Color.fromHex(0xcc00ff),
			ImageProcessing.Color.fromHex(0x00ffcc),
		];

		labels.forEach(function(_, x){
			_.forEach(function(n, y){
				if(0 < n){
					self.setPixel(x, y, colors[n % colors.length]);
				}
			});
		});

		return self;
	})
.unlock()
.update();

エッジ処理 - 閾値処理 - ラベリング
http://gyazo.com/6e89c5c3ae5c876a8d88e7e6ff2ad8a9.png
あんまり連続でラベリングする範囲が広いと「too much recursion」と言われてしまう。タイマー使うといいのかな。