Here is some working code for the form classifier. http://jsfiddle.net/R3ns3/ I pulled the threshold numbers (* Threshold variables in the code) from the air, so of course they can be tuned to get better results.
I use the bounding box, the midpoint in the subseries, the angle between the points, the polar angle from the center of the frame, and angle recognition. It can classify drawn rectangles, diamonds and circles. The code records the points when you click the mouse and tries to classify when you stop drawing.
HTML
<canvas id="draw" width="300" height="300" style="position:absolute; top:0px; left:0p; margin:0; padding:0; width:300px; height:300px; border:2px solid blue;"></canvas>
Js
var state = { width: 300, height: 300, pointRadius: 2, cornerThreshold: 125, circleThreshold: 145, rectangleThreshold: 45, diamondThreshold: 135, canvas: document.getElementById("draw"), ctx: document.getElementById("draw").getContext("2d"), drawing: false, points: [], getCorners: function(angles, pts) { var list = pts || this.points; var corners = []; for(var i=0; i<angles.length; i++) { if(angles[i] <= this.cornerThreshold) { corners.push(list[(i + 1) % list.length]); } } return corners; }, draw: function(color, pts) { var list = pts||this.points; this.ctx.fillStyle = color; for(var i=0; i<list.length; i++) { this.ctx.beginPath(); this.ctx.arc(list[i].x, list[i].y, this.pointRadius, 0, Math.PI * 2, false); this.ctx.fill(); } }, classify: function() { // get bounding box var left = this.width, right = 0, top = this.height, bottom = 0; for(var i=0; i<this.points.length; i++) { var pt = this.points[i]; if(left > pt.x) left = pt.x; if(right < pt.x) right = pt.x; if(top > pt.y) top = pt.y; if(bottom < pt.y) bottom = pt.y; } var center = {x: (left+right)/2, y: (top+bottom)/2}; this.draw("#00f", [ {x: left, y: top}, {x: right, y: top}, {x: left, y: bottom}, {x: right, y: bottom}, ]); // find average point in each sector (9 sectors) var sects = [ {x:0,y:0,c:0},{x:0,y:0,c:0},{x:0,y:0,c:0}, {x:0,y:0,c:0},{x:0,y:0,c:0},{x:0,y:0,c:0}, {x:0,y:0,c:0},{x:0,y:0,c:0},{x:0,y:0,c:0} ]; var x3 = (right + (1/(right-left)) - left) / 3; var y3 = (bottom + (1/(bottom-top)) - top) / 3; for(var i=0; i<this.points.length; i++) { var pt = this.points[i]; var sx = Math.floor((pt.x - left) / x3); var sy = Math.floor((pt.y - top) / y3); var idx = sy * 3 + sx; sects[idx].x += pt.x; sects[idx].y += pt.y; sects[idx].c ++; if(sx == 1 && sy == 1) { return "UNKNOWN"; } } // get the significant points (clockwise) var sigPts = []; var clk = [0, 1, 2, 5, 8, 7, 6, 3] for(var i=0; i<clk.length; i++) { var pt = sects[clk[i]]; if(pt.c > 0) { sigPts.push({x: pt.x / pt.c, y: pt.y / pt.c}); } else { return "UNKNOWN"; } } this.draw("#0f0", sigPts); // find angle between consecutive 3 points var angles = []; for(var i=0; i<sigPts.length; i++) { var a = sigPts[i], b = sigPts[(i + 1) % sigPts.length], c = sigPts[(i + 2) % sigPts.length], ab = Math.sqrt(Math.pow(bx-ax,2)+Math.pow(by-ay,2)), bc = Math.sqrt(Math.pow(bx-cx,2)+ Math.pow(by-cy,2)), ac = Math.sqrt(Math.pow(cx-ax,2)+ Math.pow(cy-ay,2)), deg = Math.floor(Math.acos((bc*bc+ab*ab-ac*ac)/(2*bc*ab)) * 180 / Math.PI); angles.push(deg); } console.log(angles); var corners = this.getCorners(angles, sigPts); // get polar angle of corners for(var i=0; i<corners.length; i++) { corners[i].t = Math.floor(Math.atan2(corners[i].y - center.y, corners[i].x - center.x) * 180 / Math.PI); } console.log(corners); // whats the shape ? if(corners.length <= 1) { // circle return "CIRCLE"; } else if(corners.length == 2) { // circle || diamond // difference of polar angles var diff = Math.abs((corners[0].t - corners[1].t + 180) % 360 - 180); console.log(diff); if(diff <= this.circleThreshold) { return "CIRCLE"; } else { return "DIAMOND"; } } else if(corners.length == 4) { // rectangle || diamond // sum of polar angles of corners var sum = Math.abs(corners[0].t + corners[1].t + corners[2].t + corners[3].t); console.log(sum); if(sum <= this.rectangleThreshold) { return "RECTANGLE"; } else if(sum >= this.diamondThreshold) { return "DIAMOND"; } else { return "UNKNOWN"; } } else { alert("draw neater please"); return "UNKNOWN"; } } }; state.canvas.addEventListener("mousedown", (function(e) { if(!this.drawing) { this.ctx.clearRect(0, 0, 300, 300); this.points = []; this.drawing = true; console.log("drawing start"); } }).bind(state), false); state.canvas.addEventListener("mouseup", (function(e) { this.drawing = false; console.log("drawing stop"); this.draw("#f00"); alert(this.classify()); }).bind(state), false); state.canvas.addEventListener("mousemove", (function(e) { if(this.drawing) { var x = e.pageX, y = e.pageY; this.points.push({"x": x, "y": y}); this.ctx.fillStyle = "#000"; this.ctx.fillRect(x-2, y-2, 4, 4); } }).bind(state), false);