Created
October 6, 2015 09:11
-
-
Save nandor/7e74368a449924483173 to your computer and use it in GitHub Desktop.
RANSAC implementation in JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>RANSAC</title> | |
<style type="text/css"> | |
#canvas, body, html { | |
width: 100%; | |
height: 100%; | |
margin: 0; padding: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="canvas"></canvas> | |
<script type="text/javascript"> | |
var THRESHOLD = 10; | |
var canvas = document.getElementById("canvas"); | |
var ctx = canvas.getContext('2d'); | |
var points = []; | |
var width = 0, height = 0; | |
var a = 0, b = 0, c = 0; | |
// Resizes the canvas. | |
var resize = function() { | |
width = canvas.width = window.innerWidth; | |
height = canvas.height = window.innerHeight; | |
render(); | |
}; | |
window.resize = resize; | |
window.onload = resize; | |
// Draws the canvas. | |
var render = function() { | |
ctx.clearRect(0, 0, width, height); | |
// Draw all the points. | |
ctx.fillStyle = '#000000'; | |
for (var i = 0; i < points.length; ++i) { | |
var point = points[i]; | |
ctx.fillRect(point.x, point.y, 2, 2); | |
} | |
// Draw the line. | |
ctx.strokeStyle = '#ff0000'; | |
ctx.beginPath(); | |
if (Math.abs(b) > 1e-7) { | |
ctx.moveTo( | |
0, | |
(-c - a * 0) / b | |
); | |
ctx.lineTo( | |
width, | |
(-c - a * width) / b | |
); | |
} else { | |
ctx.moveTo( | |
(-c - b * 0) / a, | |
0 | |
); | |
ctx.lineTo( | |
(-c - b * height) / a, | |
height | |
); | |
} | |
ctx.stroke(); | |
}; | |
// Computes the parameters of the line using ransac. | |
var ransac = function() { | |
if (points.length <= 2) { | |
return {a: 0, b: 0, c: 0}; | |
} | |
var count = 0, best = {}, bestCnt = 0; | |
for (var iter = 0; iter < 500; ++iter) { | |
// Select two points and fit the model. | |
var i0 = ~~(Math.random() * (points.length - 1)), i1; | |
do { | |
i1 = ~~(Math.random() * (points.length - 1)); | |
} while (i1 == i0); | |
var p0 = points[i0], p1 = points[i1]; | |
// Compute the parameters of the line. | |
var slope = (p1.y - p0.y) / (p1.x - p0.x); | |
a = -1.0; | |
b = 1.0 / slope; | |
c = p0.x - p0.y / slope; | |
// Count the number of points that fit the model. | |
count = 0; | |
for (var i = 0; i < points.length; ++i) { | |
var point = points[i]; | |
var dist = Math.abs(a * point.x + b * point.y + c) / Math.sqrt(a * a + b * b); | |
if (dist < THRESHOLD) { | |
++count; | |
} | |
} | |
// If more points were classified, break. | |
if (bestCnt < count) { | |
bestCnt = count; | |
best.a = a; | |
best.b = b; | |
best.c = c; | |
} | |
} | |
return best; | |
}; | |
// Add new points when clicking on the canvas. | |
canvas.addEventListener('click', function(evt) { | |
points.push({ | |
x: evt.pageX, | |
y: evt.pageY | |
}); | |
var line = ransac(); | |
a = line.a; | |
b = line.b; | |
c = line.c; | |
render(); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment