【问题标题】:Canvas pixels to coordinates画布像素到坐标
【发布时间】:2015-04-23 02:40:51
【问题描述】:

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

所以我做的是:

  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 通道 rgba)数组。

pMinY 和 pMaxY 似乎工作得很好,而 pMinX、pMaX 有时看起来是正确的,而另一些则是错误的。 为了测试,我创建了一个浮动的div 并根据:

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

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

【问题讨论】:

  • 您是否尝试过使用highlightCanvas.height 代替Y
  • @Roco Y 似乎是正确的。查看我对这个问题的更新。
  • “有时正确,有时错误。我的代码有什么问题”。你不能指望这样的问题得到答案。创建一个演示,以便人们了解“有时”的含义。
  • @RokoC.Buljan 可能你是对的。很难在小提琴上创建一个演示,但我会试一试。我希望有人做过类似的事情,并能在我的 X 方程中发现问题。

标签: javascript html canvas


【解决方案1】:

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

它是这样工作的:

  • 使用.getImageData获取画布上每个像素的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>

【讨论】:

  • @AvraamMavridis findImageBounds 函数查找矩形的边界 (x,y,width,height)。我只是重新绘制了矩形以显示它工作正常! ;-)
  • 我明白了。我将尝试在工作人员中实现您的逻辑。谢谢 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-04
  • 2013-02-24
  • 2011-10-15
  • 2012-03-07
  • 1970-01-01
  • 2020-06-10
  • 1970-01-01
相关资源
最近更新 更多