HTML5 Canvas图像分割

时间:2015-06-26 11:14:45

标签: javascript html5 canvas html5-canvas image-segmentation

我正在尝试从图像中删除背景(墙)的白/灰像素,以便保留前景(在我的情况下是一只手)。

我尝试操纵画布像素,但由于背景中的阴影或其他不一致性,前景提取效果不是很好。我甚至试过绿色背景,但它没有提高性能。

for (i = 0; i < imgData.width * imgData.height * 4; i += 4) {
    var r = imgDataNormal.data[i + 0];
    var g = imgDataNormal.data[i + 1];
    var b = imgDataNormal.data[i + 2];
    var a = imgDataNormal.data[i + 3];
    // compare rgb levels for green and set alphachannel to 0;
    selectedR = *a value 0 - 255*
    selectedG = *a value 0 - 255*
    selectedB = *a value 0 - 255*
    if (r <= selectedR || g >= selectedG || b <= selectedB) {
        a = 0;
    }
}

是否有任何复杂的方法或库可以使图像的背景透明?

Sample Image

2 个答案:

答案 0 :(得分:2)

您的代码中存在一些错误:

  • 最后一行a = 0除了更改局部变量外什么都不做。您必须直接在数组中修改它
  • 之后,要查看结果,您必须将像素阵列推回到上下文
  • 由于您需要(在该示例中)检查白色/灰色背景(rgb(255, 255, 255)),您需要检查像素的值是否优越,而不是低劣。并且使用and运算符而不是or允许您在此处过滤阴影的较大部分(灰色,因此每个颜色分量具有几乎相同的值)而不移除手本身,这是更多着色。

以下是一个例子:

var imgData = context.getImageData(0, 0, canvas.width, canvas.height);

for (i = 0; i < imgData.width * imgData.height * 4; i += 4) {
    var r = imgData.data[i + 0];
    var g = imgData.data[i + 1];
    var b = imgData.data[i + 2];
    var a = imgData.data[i + 3];
    // compare rgb levels for green and set alphachannel to 0;
    selectedR = 105;
    selectedG = 105;
    selectedB = 105;
    if (r >= selectedR && g >= selectedG && b >= selectedB) {
        imgData.data[i + 3] = 0;
    }
}

context.putImageData(imgData, 0, 0);

由于阴影,它仍然不完美,但它有效。

result

答案 1 :(得分:1)

将像素从RGB转换为HSL,然后在像素上运行阈值滤镜以删除任何内容(通过将像素的alpha设置为完全透明),饱和度小于0.12(测量饱和度)在0..1的范围内 - 通过反复试验找到该值。

<强>的JavaScript

function rgbToHsl( r, g, b ){
  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;

  if(max == min){
      h = s = 0; // achromatic
  }else{
      var d = max - min;
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
      switch(max){
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
      }
      h /= 6;
  }
  return [h, s, l];
}

function thresholdHsl(pixels,lower,upper){
  var d = pixels.data;
   var createTest = function( lower, upper ){
     return lower <= upper
            ? function(v){ return lower <= v && v <= upper; }
            : function(v){ return lower <= v || v <= upper; };
   }
   var h = createTest( lower[0], upper[0] );
   var s = createTest( lower[1], upper[1] );
   var l = createTest( lower[2], upper[2] );

  for (var i=0; i<d.length; i+=4) {
   var hsl = rgbToHsl( d[i], d[i+1], d[i+2] );
   if ( !h(hsl[0]) || !s(hsl[1]) || !l(hsl[2]) ){
     d[i+3] = 0;
   }
  }
}

var img = new Image();

img.onload = function() {
  var canvas = document.getElementById('myCanvas');
  var ctx    = canvas.getContext('2d');
  ctx.drawImage(img,0,0);
  var pixels = ctx.getImageData(0,0,canvas.width,canvas.height);
  thresholdHsl(pixels,[0,0.12,0],[1,1,1]);
  ctx.putImageData(pixels, 0, 0);
};
img.src = 'Hand.png';

<强> HTML

<canvas id="myCanvas" width="638" height="475"></canvas>

<强>输出 Threshold on Saturation

可以通过去除图片中的噪声来尝试清理边缘来进一步改进。