【问题标题】:HTML5 Canvas image segmentationHTML5 Canvas 图像分割
【发布时间】:2015-07-02 21:55:04
【问题描述】:

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

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

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;
    }
}

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

【问题讨论】:

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


    【解决方案1】:

    你的代码有几个错误:

    • 最后一行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);
    

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

    【讨论】:

    • 感谢您的回答,但我已经能够达到这个结果。我没有在此处包含该代码,因为它仍然无法从图像中排除阴影。是否可以将这个结果细化为只得到手,没有阴影?
    • 要消除阴影,请返回使用绿屏,然后将每个像素从 RGB 转换为 HSV 或 HSL(代码常用)。然后使用 hue 值查找色调为 120 度的像素(+/- 一点,具体取决于您的色彩蒙版的确切颜色)并排除这些像素。
    • (阴影应该调整 L 或 V,但不影响 H)
    • 如果图像来源不佳(戴上我的视频专业人士的帽子),您将永远无法获得良好的效果:确保您的图像来源光线充足、清晰且光线不足手臂(这将消除阴影)。对于后者,请使用带有白色漫射器和光源的有机玻璃。确保使用手动曝光(自动将尝试将白色减少到 80% 灰色)。所有光源都需要具有相同的色彩平衡。如果此建议环境可用,我将推荐使用绿屏,因为您会遇到颜色污染/色偏。 HSL=更好但价格昂贵
    【解决方案2】:

    将像素从 RGB 转换为 HSL,然后在像素上运行阈值过滤器以移除任何饱和度低于 0.12 的内容(通过将像素的 Alpha 设置为完全透明)(以 @987654323 的比例测量饱和度@ - 该值是通过反复试验找到的)。

    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>
    

    输出

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

    【讨论】:

      猜你喜欢
      • 2011-07-09
      • 2012-05-18
      • 2014-12-17
      • 2011-12-09
      • 2011-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多