【问题标题】:Validate canvas drawing验证画布绘图
【发布时间】:2014-04-12 12:03:29
【问题描述】:

我使用 HTML5 Canvas 制作了这个小绘图应用程序,孩子们可以在其中学习如何写字母和数字。我想知道字母/数字是否绘制正确。

我尝试使用this 之类的方法来检测简单的直线,例如数字“1”。

但我不知道如何检测复杂的形状,例如数字“2”、“8”(嗯,除了直线以外的任何形状)

帮助?

【问题讨论】:

    标签: javascript html canvas drawing


    【解决方案1】:

    如果你只是想给他们写“2”的肌肉记忆,那么你可以把“2”的轮廓放在画布上,让他们填满那个轮廓。

    如果在轮廓内的鼠标点比在轮廓外的鼠标点多,那么它们可能绘制了轮廓。

    但是,要“召回”一个数字并将其写入画布,您将需要字符识别(!)。

    我刚刚搜索了一下,发现了这个有趣的数字识别尝试。

    http://www.heatonresearch.com/fun/ocr

    [更新:简单的“排队”游戏示例]

    游戏的运作方式如下:

    • 用白色填充在画布上勾勒出数字“2”的轮廓
    • 使用 context.getImageData 保存像素数组
    • “2”内的像素将具有 alpha>20
    • “2”以外的像素将具有 alpha
    • 让孩子们在“2”内拖动鼠标
    • 监听 mousemove 事件
    • 测试鼠标下像素的alpha值
    • (alpha20 表示在“2”之内)
    • 如果他们在“2”之内,那么他们的分数加 1
    • 如果他们在“2”之外,则从他们的分数中减去 1
    • (可选)如果“2”在内部,则将其设为绿色作为正确性的视觉反馈

    当他们松开鼠标时,他们的分数就会出现。分数表示鼠标内数减去鼠标外数。

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

    鼠标在数字内——数字是绿色的,表示正面的视觉反馈

    鼠标在号码外——没有正面的视觉反馈

    <!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: white; }
        #canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
        var $canvas=$("#canvas");
        var canvasOffset=$canvas.offset();
        var offsetX=canvasOffset.left;
        var offsetY=canvasOffset.top;
        var scrollX=$canvas.scrollLeft();
        var scrollY=$canvas.scrollTop();
    
    
        ctx.font="216px arial";
        ctx.fillStyle="white";
        ctx.fillText("2",100,200);
        ctx.strokeText("2",100,200);
    
        var cw=canvas.width;
        var ch=canvas.height;
        var imgData=ctx.getImageData(0,0,cw,ch);
        var data=imgData.data;
    
        var isDown=false;
        var wasInside=true;
        var score=0;
    
        function draw(mouseX,mouseY){
    
            var alpha = data[((cw*mouseY)+mouseX)*4+3];
    
            score+=(alpha>19?1:-1);
    
            if(alpha<20 && wasInside){
                wasInside=false;
                ctx.fillStyle="white";
                ctx.fillRect(0,0,cw,ch);
                ctx.fillStyle="white";
                ctx.fillText("2",100,200);
                ctx.strokeText("2",100,200);
            }else if(alpha>19 && !wasInside){
                wasInside=true;
                ctx.fillStyle="white";
                ctx.fillRect(0,0,cw,ch);
                ctx.fillStyle="green";
                ctx.fillText("2",100,200);
                ctx.strokeText("2",100,200);
            }
    
        }
    
        function handleMouseDown(e){
          e.preventDefault();
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
          var alpha = data[((cw*mouseY)+mouseX)*4+3];
          wasInside=(alpha<20);
          score=0;
          isDown=true;
          draw(mouseX,mouseY);
        }
    
        function handleMouseUp(e){
          e.preventDefault();
          isDown=false;
          $("#score").text("Score: "+score);
        }
    
        function handleMouseOut(e){
          e.preventDefault();
          isDown=false;
        }
    
        function handleMouseMove(e){
          if(!isDown){return;}
          e.preventDefault();
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
          draw(mouseX,mouseY);
        }
    
        $("#canvas").mousedown(function(e){handleMouseDown(e);});
        $("#canvas").mousemove(function(e){handleMouseMove(e);});
        $("#canvas").mouseup(function(e){handleMouseUp(e);});
        $("#canvas").mouseout(function(e){handleMouseOut(e);});
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <h4>Drag inside the number<br>Number stays green while you're inside.</h4>
        <h3 id="score">Score:</h3>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

    • 我只是想给他们肌肉记忆。您能否解释或指出我如何知道内部是否有更多鼠标点?
    • 当然。我更新了我的答案,包括一个简单的游戏演示,该演示对孩子在数字内拖拽的程度进行评分。我的游戏版本很简单。我相信你可以为孩子们“幻想”!
    • @markeE 非常感谢伙计!这正是我想要的:D
    【解决方案2】:

    这是一个复杂的领域,可能超出了 SO 的范围,但请研究诸如神经网络或在线识别(当他们画画时)之类的东西。

    这是一种神经网络方法(C++ 中的源代码;应该有点容易翻译成 JavaScript)(它带有一个权重文件):
    Neural Network for Recognition of Handwritten Digits

    这是一个使用多重卷积神经网络的在线方法(C#代码):
    Online handwriting recognition using multi convolution neural networks

    更多主题:
    https://en.wikipedia.org/wiki/Handwriting_movement_analysis
    https://en.wikipedia.org/wiki/Handwriting_recognition

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 2017-03-26
      • 1970-01-01
      • 2018-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-01
      • 2017-08-10
      相关资源
      最近更新 更多