Skip to content

Instantly share code, notes, and snippets.

@nandor
Created October 6, 2015 09:11
Show Gist options
  • Save nandor/7e74368a449924483173 to your computer and use it in GitHub Desktop.
Save nandor/7e74368a449924483173 to your computer and use it in GitHub Desktop.
RANSAC implementation in JS
<!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