繁体   English   中英

在画布中查找所有黑色矩形

[英]Find all black rectangles in canvas

假设我有一张扫描纸,上面有一些黑色填充的矩形,我想对它们全部进行定位,以获取它们的坐标(X和Y)以及尺寸(宽度和高度)。

我需要什么准确的算法吗? 我是Java和Canvas像素处理的新手,我需要一些帮助。 提前致谢!

识别所有黑色矩形的x,y,width,height涉及以下步骤:

  1. 使用context.getImageData可以获取画布上所有r,g,b,a像素信息的数组。

  2. 扫描像素颜色以找到任何一个黑色像素。

  3. 找到包含该黑色像素的黑色矩形的边界框。

  4. 该边界框将为您提供一个黑色矩形的x,y,宽度,高度。

  5. 清除该黑色矩形,以便在搜索下一个黑色矩形时找不到该矩形。

  6. 重复步骤1,直到识别出所有矩形。

这是示例代码和演示: http : //jsfiddle.net/m1erickson/3m0dL368/

<!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.com/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+")";

    cw=canvas.width;
    ch=canvas.height;
    ctx.fillStyle="white";
    ctx.fillRect(0,0,canvas.width,canvas.height);
    drawTestRect(30,30,50,50,"1");
    drawTestRect(100,30,50,50,"2");
    drawTestRect(170,30,50,50,"3");

    function drawTestRect(x,y,w,h,label){
        ctx.fillStyle="black";
        ctx.fillRect(x,y,w,h);
        ctx.fillStyle="white";
        ctx.font="24px verdana";
        ctx.fillText(label,x+10,y+25);        
    }

    function clipBox(data){
        var pos=findEdge(data);
        if(!pos.valid){return;}
        var bb=findBoundary(pos,data);
        alert("Found target at "+bb.x+"/"+bb.y+", size: "+bb.width+"/"+bb.height);            
        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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM