ラベリング
http://www.microsoft.com/japan/msdn/academic/Articles/Algorithm/03/
これ使用
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();
エッジ処理 - 閾値処理 - ラベリング
あんまり連続でラベリングする範囲が広いと「too much recursion」と言われてしまう。タイマー使うといいのかな。
自動コントラスト
画像濃度変換処理
濃度の最小値が0, 最大値が255になるようにする濃度変換。与える関数は、
var f = function(x){ var a = 255 / (max - min); var b = - a * min; return a * x + b; };
一般的な画像では最大値≒255、最小値≒0ということが多いので、見た目で変わってくることはほとんどない、と思う。明るさの調節と一緒に使うと効果が分かりやすい。
これ使用
ImageProcessing.Color.prototype.intensity = function(v){ return new Color(this.r + v, this.g + v, this.b + v); }; ImageProcessing.prototype.autoContrast = function(){ var self = this; var _f = function(max, min){ if(max >= 255 && min <= 0) return function(x){ return x; }; var a = 255 / (max - min); var b = - a * min; return function(x){ return a * x + b; }; }; var max = this.max(); var min = this.min(); if(max.toString() == (new ImageProcessing.Color(255, 255, 255)).toString() && min.toString() == (new ImageProcessing.Color( 0, 0, 0)).toString()) return this; var f = { r: _f(max.r, min.r), g: _f(max.g, min.g), b: _f(max.b, min.b) }; this.each(function(px, x, y){ self.setPixel(x, y, new ImageProcessing.Color(f.r(px.r), f.g(px.g), f.b(px.b))); }); return this; }; var ip = ImageProcessing.load("img.png"); ip.lock() .each(function(px, x, y){ ip.setPixel(x, y, px.intensity(50)); }) .autoContrast() .update();