通过图像映射坐标提取图像的一部分并将其显示在 canvas 中

Extract part of image by its image map coordinates and display it inside a canvas

我有一个正在显示的图像 canvas 我有这样的坐标

428,361,432,374,475,399,470,472,420,
494,400,486,328,461,183,409,176,386,
178,356,182,345,270,309,192,288,072,
257,069,228,069,219,077,212,112,205,
133,207,185,201,213,203,277,215,291,
220,298,222,323,225,388,235,418,244,
412,269,393,312,387,332,388,349,407,
356,414,360

采用 <area> 标记格式。

我想做的是从图像中提取该区域并将其(提取的区域)显示在另一个 canvas。

我该怎么做?

谢谢

这是我用来制作这些坐标的代码

function clipIt(){
  // calculate the size of the user's clipping area
  if(points=="")
   bootbox.alert("Not selected", function() {

    });
  else{
  var minX=10000;
  var minY=10000;
  var maxX=-10000;
  var maxY=-10000;
  for(var i=1;i<points.length;i++){
    var p=points[i];
    if(p.x<minX){minX=p.x;}
    if(p.y<minY){minY=p.y;}
    if(p.x>maxX){maxX=p.x;}
    if(p.y>maxY){maxY=p.y;}
  }
  var width=maxX-minX;
  var height=maxY-minY;

  // clip the image into the user's clipping area
  ctx.save();
  ctx.clearRect(0,0,cw,ch);
  ctx.beginPath();
  ctx.moveTo(points[0].x,points[0].y);
  for(var i=1;i<points.length;i++){
    var p=points[i];
    ctx.lineTo(points[i].x,points[i].y);
  }
  ctx.closePath();
  ctx.clip();
  ctx.drawImage(img,0,0);
  ctx.restore();

  // create a new canvas 
  var c=document.createElement('canvas');
  var cx=c.getContext('2d');

  // resize the new canvas to the size of the clipping area
  c.width=width;
  c.height=height;

  // draw the clipped image from the main canvas to the new canvas
  cx.drawImage(canvas, minX,minY,width,height, 0,0,width,height);

  // create a new Image() from the new canvas
  var clippedImage=new Image();
  //clippedImage.name="img"+ nameimageis 
  clippedImage.id="img"+ nameimageis
  clippedImage.onload=function(){
    // append the new image to the page

    //document.body.appendChild(clippedImage );
    new_parts=new_parts+1;
    $("#contain").append(clippedImage)
    $("#img"+nameimageis ).wrap( "<div class='ins' id='in_"+nameimageis+"'></div>" );
    $("#in_"+nameimageis ).append("<input type='hidden' id='new_"+nameimageis+"' value='new'/><div class='inner' id='inner_"+nameimageis+"' onclick='removeit("+nameimageis+")'></div>");

    nameimageis++; 
  }
  clippedImage.src=c.toDataURL();


  // clear the previous points 
  points.length=0;

  // redraw the image on the main canvas for further clipping
  drawImage(1);

}
}

您的面积点实际上是多边形的 point-pairs。该多边形是源图像的所需区域。

以下是从源图像中提取区域映射像素的方法:

  • 计算区域坐标的边界框:minX,minY & maxX,maxY

  • 将目标 canvas 调整为边界框的大小:

    width=maxX-minX, height=maxY-minY
    
  • 在目的地创建剪切路径。裁剪路径是将原来的区域移动到目的地canvas.

    的top-left
    // draw the clipping path
    ctx.beginPath();
    ctx.moveTo(pointpairs[0]-minX,pointpairs[1]-minY);
    for(var i=2;i<pointpairs.length;i+=2){
        var x=pointpairs[i];
        var y=pointpairs[i+1];
        ctx.lineTo(x-minX,y-minY);
    }
    ctx.closePath();
    ctx.clip();
    
  • 将图像绘制到目的地 canvas,但偏移 minY 和 minY

    ctx.drawImage(img,-minX,-minY);
    

这是示例代码和演示:

var srcCanvas=document.getElementById("source");
var sctx=srcCanvas.getContext("2d");
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

var pointpairs=[
  428,361,432,374,475,399,470,472,420,
  494,400,486,328,461,183,409,176,386,
  178,356,182,345,270,309,192,288,072,
  257,069,228,069,219,077,212,112,205,
  133,207,185,201,213,203,277,215,291,
  220,298,222,323,225,388,235,418,244,
  412,269,393,312,387,332,388,349,407,
  356,414,360];
var minX=1000000;
var minY=minX;
var maxX=-1000000;
var maxY=maxX;

for(var i=0;i<pointpairs.length;i+=2){
  var x=pointpairs[i];
  var y=pointpairs[i+1];
  if(x<minX){minX=x;}
  if(y<minY){minY=y;}
  if(x>maxX){maxX=x;}
  if(y>maxY){maxY=y;}
}

var img=new Image();
img.onload=start;
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/transportation.jpg';
function start(){

  srcCanvas.width=img.width;
  srcCanvas.height=img.height;

  sctx.drawImage(img,0,0);

  // draw the source image
  // and also stroke the text area
  sctx.lineWidth=2;
  sctx.strokeStyle='blue';
  sctx.beginPath();
  sctx.moveTo(pointpairs[0],pointpairs[1]);
  for(var i=2;i<pointpairs.length;i+=2){
    var x=pointpairs[i];
    var y=pointpairs[i+1];
    sctx.lineTo(x,y);
  }
  sctx.closePath();
  sctx.stroke();

  // resize the canvas to the <area> bounding box size
  canvas.width=maxX-minX;
  canvas.height=maxY-minY;

  // draw the clipping path
  ctx.beginPath();
  ctx.moveTo(pointpairs[0]-minX,pointpairs[1]-minY);
  for(var i=2;i<pointpairs.length;i+=2){
    var x=pointpairs[i];
    var y=pointpairs[i+1];
    ctx.lineTo(x-minX,y-minY);
  }
  ctx.closePath();
  ctx.clip();

  ctx.drawImage(img,-minX,-minY);

}
body{ background-color:black; padding:10px; }
canvas{border:1px solid red;}
<canvas id="source" width=300 height=300></canvas>
<br/>
<canvas id="canvas" width=300 height=300></canvas>