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

Javascript 在画布中查找所有黑色矩形,javascript,html5-canvas,Javascript,Html5 Canvas,假设我有一张扫描过的纸,上面有一些黑色的矩形,我想对它们进行定位,得到它们的坐标(X和Y)和尺寸(宽度和高度) 有没有精确的算法可以满足我的需要?我对Javascript和画布的像素处理还不熟悉,需要一些帮助。提前谢谢 识别所有黑色矩形的x、y、宽度和高度包括以下步骤: 使用context.getImageData获取画布上所有r、g、b、a像素信息的数组 扫描像素颜色以查找任何一个黑色像素 找到包含一个黑色像素的黑色矩形的边界框 该边界框将为您提供一个黑色矩形的x、y、宽度和高度 清除该黑色矩

假设我有一张扫描过的纸,上面有一些黑色的矩形,我想对它们进行定位,得到它们的坐标(X和Y)和尺寸(宽度和高度)


有没有精确的算法可以满足我的需要?我对Javascript和画布的像素处理还不熟悉,需要一些帮助。提前谢谢

识别所有黑色矩形的x、y、宽度和高度包括以下步骤:

  • 使用
    context.getImageData
    获取画布上所有r、g、b、a像素信息的数组

  • 扫描像素颜色以查找任何一个黑色像素

  • 找到包含一个黑色像素的黑色矩形的边界框

  • 该边界框将为您提供一个黑色矩形的x、y、宽度和高度

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

  • 重复步骤#1,直到识别出所有矩形

  • 下面是示例代码和演示:

    
    正文{背景色:象牙;}
    画布{边框:1px纯红;}
    #剪辑{边框:1px纯蓝色;填充:5px;}
    img{margin:3px;}
    $(函数(){
    var canvas=document.getElementById(“canvas”);
    var ctx=canvas.getContext(“2d”);
    var-cw,ch;
    //背景定义
    //选项:查看左上角的像素并假设==背景
    //然后自动设置这些变量
    var isTransparent=false;
    var bkColor={r:255,g:255,b:255};
    var bkFillColor=“rgb(“+bkColor.r+”,“+bkColor.g+”,“+bkColor.b+”);
    cw=画布宽度;
    ch=画布高度;
    ctx.fillStyle=“白色”;
    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”);
    函数drawTestRect(x、y、w、h、label){
    ctx.fillStyle=“黑色”;
    ctx.fillRect(x,y,w,h);
    ctx.fillStyle=“白色”;
    ctx.font=“24px verdana”;
    ctx.fillText(标签,x+10,y+25);
    }
    功能剪贴簿(数据){
    var pos=findEdge(数据);
    如果(!pos.valid){return;}
    var bb=findBoundary(位置、数据);
    警报(“发现目标位于“+bb.x+”/“+bb.y+”,大小:“+bb.width+”/“+bb.height”);
    剪贴画(bb.x,bb.y,bb.width,bb.height);
    如果(透明){
    //清除裁剪区域
    //加上几个像素以清除任何抗锯齿
    ctx.clearRect(bb.x-2,bb.y-2,bb.width+4,bb.height+4);
    }否则{
    //用黑色填充剪裁区域
    //加上几个像素以清除任何抗锯齿
    ctx.fillStyle=bkFillColor;
    ctx.fillRect(bb.x-2,bb.y-2,bb.width+4,bb.height+4);
    }
    }
    函数xyinimage(数据,x,y){
    //查找像素x,y的r,g,b,a的起始索引
    var start=(y*cw+x)*4;
    如果(透明){
    返回(数据[开始+3]>25);
    }否则{
    var r=数据[start+0];
    var g=数据[start+1];
    var b=数据[start+2];
    var a=data[start+3];//像素alpha(不透明度)
    var deltaR=数学绝对值(bkColor.r-r);
    var deltaG=Math.abs(bkColor.g-g);
    var deltaB=数学abs(bkColor.b-b);
    
    返回((deltaR@josemmo:尽量与回答问题的人尽可能少地努力。
    <!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>