javascript - Canvas 像素到坐标

标签 javascript html canvas

我有一个 Canvas ,宽度 = 900,高度 = 574。我有 Canvas 的所有像素。 Canvas 内部有一些矩形,知道矩形的所有像素我想要的是找到矩形的4个点的坐标,然后找到矩形的宽度和高度。

enter image description here

所以我所做的是:

  pMinX = (_.min(points)/ 4) % highlightCanvas.width
  pMinY = Math.floor((_.min(points) / 4) / highlightCanvas.width)
  pMaxX = (_.max(points) / 4) % highlightCanvas.width
  pMaxY = Math.floor((_.max(points) / 4) / highlightCanvas.width)

Points 是我想要查找其坐标的矩形的像素数组(4 channel rgba)。

pMinY 和 pMaxY 似乎工作良好,而 pMinX、pMaX 有时看起来正确,而其他则错误。 为了测试,我创建了一个 float div 并根据以下内容调整其大小:

  {
    width:  pMaxX - pMinX
    height: pMaxY - pMinY
  }

div 的高度始终是正确的。但宽度也有失败的情况。 知道为什么有时计算失败吗?

最佳答案

以下带注释的代码显示了如何计算图像中鲑鱼色矩形的边界框(x、y、宽度、高度)。

enter image description here

它的工作原理如下:

  • 使用 .getImageData 获取 Canvas 上每个像素的 r、g、b、a 值。

  • 设置像素的 rgba 必须满足的测试才能被视为“在所需的矩形内” 在您的示例中,鲑鱼矩形由 2 种颜色组成,因此这测试将捕获矩形内的所有像素:

    // create an array to hold tests that are used to
    // find your desired pixels. The tests should be functions
    // that return true for your desired rgba pixel values
    // (substitue whatever algorithm test that are necessary for your design)
    var tests=[];
    
    
    // add a test into the tests[] array
    tests.push(function(r,g,b,a){
        return(
            (r==251 && g==115 && b==119)||
            (r==249 && g==100 && b==107)
        );
    });
    
  • 确定满足测试的像素的 minX、minY、maxX 和 maxY

  • 根据确定的最小值和最大值计算矩形像素的边界框:

    var bounds={
        x:minX,
        y:minY,
        width:maxX-minX,
        height:maxY-minY
    };
    

重要说明:要允许 .getImageData,您必须满足安全限制。通常的方法是在与网页相同的域中提供图像。或者,您可以设置托管图像的服务器以将该图像提供给任何匿名请求者。

示例代码和演示:

// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

// load the image
var img=new Image();
// the image must satisfy cross-origin restrictions
// or else we can't use .getImageData
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/findRect.png";
function start(){

  // resize the canvas to the image size 
  // and draw the image onto the canvas
  cw=canvas.width=img.width;
  ch=canvas.height=img.height;
  ctx.drawImage(img,0,0);

  // create an array to hold tests that are used to
  // find your desired pixels. The tests should be functions
  // that return true for your desired rgba pixel values
  // (substitue whatever algorithm test that are necessary for
  //    your design)
  var tests=[];

  // sample test returns true if matching the 2 colors making up the rect
  tests.push(function(r,g,b,a){
    return(
      (r==251 && g==115 && b==119)||
      (r==249 && g==100 && b==107)
    );
  });

  // find the bounds of all pixels meeting the prescribed test(s)
  var bounds=findImageBounds(tests);   

  // testing...draw just the discovered rect to a second canvas
  var c=document.createElement('canvas');
  var cctx=c.getContext('2d');
  document.body.appendChild(c);
  c.width=cw;
  c.height=ch;
  cctx.drawImage(canvas,
                 bounds.x,bounds.y,bounds.w,bounds.h,
                 bounds.x,bounds.y,bounds.w,bounds.h
                );

}

function findImageBounds(tests){

  // get the rgba color values for all pixels on the canvas
  var d=ctx.getImageData(0,0,cw,ch).data;

  // iterate over each pixel
  // find the min/max X,Y of pixels where all tests are true
  var minX=1000000;
  var minY=1000000;
  var maxX=-1000000;
  var maxY=-1000000;
  var hits=0;
  for(var y=0;y<ch;y++){
    for(var x=0;x<cw;x++){
      // n==the position in the rgba array for canvas position x,y
      n=(y*cw+x)*4;
      // the rgba values at this pixel
      r=d[n];
      g=d[n+1];
      b=d[n+2];
      a=d[n+3];
      // run all tests on this pixel
      var testsTrue=true;
      for(var i=0;i<tests.length;i++){
        testsTrue=testsTrue && tests[i](r,g,b,a);
      }
      // if this pixel meets all tests
      // see if it influences our boundary 
      if(testsTrue){
        hits++;
        if(x<minX){minX=x;}
        if(y<minY){minY=y;}
        if(x>minX){maxX=x;}
        if(y>maxY){maxY=y;}
      }
    }}
  // return the x,y,width,height of the bounding box
  // of pixels meeting all the supplied tests
  return({x:minX,y:minY,w:maxX-minX,h:maxY-minY,pixelCount:hits});
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<h4>The original canvas</h4>
<canvas id="canvas" width=300 height=300></canvas>
<h4>Just the rect from the canvas</h4>

关于javascript - Canvas 像素到坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29792199/

相关文章:

javascript - 文本到语音与化身口型同步,无插件

c# - 以编程方式更改 StackPanel 在 Canvas 上的位置

javascript - 是否有一种 jQuery 方法可以仅迭代对象自己的属性?

javascript - 更改跨度文本?

javascript - 如何在 CSS 转换期间阻止处理事件循环中的其他消息?

html - 不必要的类与元素选择器(CSS 性能)

javascript - 需要修复 Canvas 绘图尺寸

javascript - EasleJS Canvas 不显示指定的 Google 字体

javascript - Windows Media Player 是否有文档化的 JavaScript API?

javascript - 将 material-ui 为子组件生成的样式放在为父组件生成的样式之后?