最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Find squaresrectangles in canvas - Stack Overflow

programmeradmin2浏览0评论

I honestly have no idea where to even really look for this. I looked on SO but the question were far more plex like detecting cars or plex shapes for games. I merely have a canvas (the HTML5 element) with an image in it that has a bunch of rectangles and squares with images inside of them and want to detect each one, "cut them out", and go through them one by one. The piece I'm stuck on is finding the shapes and then getting their coords. These aren't images I'm drawing either, but images others are uploading and then I draw onto a canvas.

Think something like:

+------------------+
|  ----  ---  ---- |
|  |  |  | |  |  | |
|  ----  ---  ---- |
|  --------------- |
|  |             | |
|  --------------- |
|                  |
+------------------+

And I want to remove each of those 4 blocks so I could go through them one by one like:

----     ---     ----     ---------------
|  | =>  | | =>  |  | =>  |             |
----     ---     ----     ---------------

I honestly have no idea where to even really look for this. I looked on SO but the question were far more plex like detecting cars or plex shapes for games. I merely have a canvas (the HTML5 element) with an image in it that has a bunch of rectangles and squares with images inside of them and want to detect each one, "cut them out", and go through them one by one. The piece I'm stuck on is finding the shapes and then getting their coords. These aren't images I'm drawing either, but images others are uploading and then I draw onto a canvas.

Think something like:

+------------------+
|  ----  ---  ---- |
|  |  |  | |  |  | |
|  ----  ---  ---- |
|  --------------- |
|  |             | |
|  --------------- |
|                  |
+------------------+

And I want to remove each of those 4 blocks so I could go through them one by one like:

----     ---     ----     ---------------
|  | =>  | | =>  |  | =>  |             |
----     ---     ----     ---------------
Share Improve this question asked Feb 19, 2014 at 8:12 Oscar GodsonOscar Godson 32.8k42 gold badges125 silver badges206 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7

[ An outline of how to do Auto-clipping of the rectangles ]

First, size the canvas to the image size and drawImage the image on the canvas.

Then for each rectangle in the canvas image:

  • Use getImageData to get an array of every pixel color on your canvas image.
  • Start scanning the colors from top-left.
  • When you hit a non-background color you've hit a rectangle's side.
  • (You must input the background color or assume the top-left pixel defines the background color)
  • Walk the rectangle in a clockwise direction until you are back to the starting spot.
  • ("Walk" means travel vertically/horizontally following the border pixel color).
  • You've got the bounding area of the rectangle.
  • (You need to bound a slightly larger area because of anti-aliased pixels).
  • Create a temporary canvas and size it to the discovered bounding box size.
  • Use context.drawImage's clipping parameters to copy the bounded rect from the original canvas to the temporary canvas.
  • Use canvas.toDataURL to save the temp canvas as an image.
  • Clear the rectangles pixels off the canvas using context.clearRect.
  • Begin the process again to find the next rectangle.

Here's code and a Demo showing auto-clipping to images: http://jsfiddle/m1erickson/33tf2/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery./jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
    #clips{border:1px solid blue; padding:5px;}
    img{margin:3px;}        
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw,ch;        

    // background definition
    // OPTION: look at the top-left pixel and assume == background
    //         then set these vars automatically
    var isTransparent=false;
    var bkColor={r:255,g:255,b:255};
    var bkFillColor="rgb("+bkColor.r+","+bkColor.g+","+bkColor.b+")";

    // load test image
    var img=new Image();
    img.crossOrigin="anonymous";
    img.onload=start;
    img.src="https://dl.dropboxusercontent./u/139992952/multple/temp2a.png";        

    function start(){
        // draw the test image on the canvas
        cw=canvas.width=img.width/2;
        ch=canvas.height=img.width/2;
        ctx.drawImage(img,0,0,cw,ch);
    }


    function clipBox(data){
        var pos=findEdge(data);
        if(!pos.valid){return;}
        var bb=findBoundary(pos,data);
        clipToImage(bb.x,bb.y,bb.width,bb.height);
        if(isTransparent){
            // clear the clipped area
            // plus a few pixels to clear any anti-aliasing
            ctx.clearRect(bb.x-2,bb.y-2,bb.width+4,bb.height+4);
        }else{
            // fill the clipped area with the bkColor
            // plus a few pixels to clear any anti-aliasing
            ctx.fillStyle=bkFillColor;
            ctx.fillRect(bb.x-2,bb.y-2,bb.width+4,bb.height+4);
        }
    }

    function xyIsInImage(data,x,y){
        // find the starting index of the r,g,b,a of pixel x,y
        var start=(y*cw+x)*4;
        if(isTransparent){
            return(data[start+3]>25);
        }else{
            var r=data[start+0];
            var g=data[start+1];
            var b=data[start+2];
            var a=data[start+3];  // pixel alpha (opacity)
            var deltaR=Math.abs(bkColor.r-r);
            var deltaG=Math.abs(bkColor.g-g);
            var deltaB=Math.abs(bkColor.b-b);
            return(!(deltaR<5 && deltaG<5 && deltaB<5 && a>25));
        }
    }

    function findEdge(data){
        for(var y=0;y<ch;y++){
        for(var x=0;x<cw;x++){
            if(xyIsInImage(data,x,y)){
                return({x:x,y:y,valid:true});
            }
        }}
        return({x:-100,y:-100,valid:false});
    }

    function findBoundary(pos,data){
        var x0=x1=pos.x;
        var y0=y1=pos.y;
        while(y1<=ch && xyIsInImage(data,x1,y1)){y1++;}
        var x2=x1;
        var y2=y1-1;
        while(x2<=cw && xyIsInImage(data,x2,y2)){x2++;}
        return({x:x0,y:y0,width:x2-x0,height:y2-y0+1});
    }

    function drawLine(x1,y1,x2,y2){
        ctx.beginPath();
        ctx.moveTo(x1,y1);
        ctx.lineTo(x2,y2);
        ctx.strokeStyle="red";
        ctx.lineWidth=0.50;
        ctx.stroke();
    }

    function clipToImage(x,y,w,h){
        // don't save anti-alias slivers
        if(w<3 || h<3){ return; }
        // save clipped area to an img element
        var tempCanvas=document.createElement("canvas");
        var tempCtx=tempCanvas.getContext("2d");
        tempCanvas.width=w;
        tempCanvas.height=h;
        tempCtx.drawImage(canvas,x,y,w,h,0,0,w,h);
        var image=new Image();
        image.width=w;
        image.height=h;
        image.src=tempCanvas.toDataURL();
        $("#clips").append(image);
    }

    $("#unbox").click(function(){
        var imgData=ctx.getImageData(0,0,cw,ch);
        var data=imgData.data;
        clipBox(data);
    });

}); // end $(function(){});
</script>
</head>
<body>
    <button id="unbox">Clip next sub-image</button><br>
    <canvas id="canvas" width=300 height=150></canvas><br>
    <h4>Below are images clipped from the canvas above.</h4><br>
    <div id="clips"></div>
</body>
</html>

If you have only rectangles with borders in canvas, then loop canvas pixels and check for sequence of same color (find corner of box). HTML5 canvas data

Log each drawn shape's details into an array. At some point you or someone else must be telling the canvas to insert these rectangles and squares, so surely you should be logging those details:

var shapes = []

// Then in some sort of listener
shapes.push({x:shapesX,y:shapesY,w:shapesW,h:shapesH})

Acquire these shape details by listening to the mouse interactions with the canvas (if that is how you draw to the canvas):

  • mousedown - log initial X/Y
  • mouseup - log the distance the users pointer has travelled from the initial X/Y to get the width and height
发布评论

评论列表(0)

  1. 暂无评论