Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Commit

Permalink
separate out non-max suppression overlap code
Browse files Browse the repository at this point in the history
  • Loading branch information
harthur committed Oct 11, 2012
1 parent 5eed653 commit 778d6fb
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 57 deletions.
69 changes: 12 additions & 57 deletions kittydar.js
Original file line number Original file line Diff line number Diff line change
@@ -1,5 +1,6 @@
var brain = require("brain"), var brain = require("brain"),
hog = require("hog-descriptor"); hog = require("hog-descriptor"),
nms = require("./nms");


var network = require("./network.js"); var network = require("./network.js");


Expand Down Expand Up @@ -59,7 +60,7 @@ var kittydar = {
var kitties = kittydar.detectAtScale(resize.imagedata, resize.scale); var kitties = kittydar.detectAtScale(resize.imagedata, resize.scale);
cats = cats.concat(kitties); cats = cats.concat(kitties);
}); });
cats = this.combineOverlaps(cats); cats = nms.combineOverlaps(cats, params.overlapThresh, params.minOverlaps);


return cats; return cats;
}, },
Expand Down Expand Up @@ -140,36 +141,6 @@ var kittydar = {
} }
} }
return cats; return cats;
},

combineOverlaps: function(rects, overlap, min) {
// non-maximum suppression - remove overlapping rects
overlap = overlap || this.overlapThresh;
min = min || this.minOverlaps;

for (var i = 0; i < rects.length; i++) {
var r1 = rects[i];
r1.tally = 0; // number of rects it's suppressed

for (var j = 0; j < i; j++) {
r2 = rects[j];

if (doesOverlap(r1, r2)) {
if (r1.prob > r2.prob) {
r2.suppressed = true;
r1.tally += 1 + r2.tally;
}
else {
r1.suppressed = true;
r2.tally += 1 + r1.tally;
}
}
}
}
// only take a rect if it wasn't suppressed by any other rect
return rects.filter(function(rect) {
return !rect.suppressed && rect.tally >= min;
})
} }
} }


Expand All @@ -194,34 +165,18 @@ function resizeCanvas(canvas, width, height) {
return resizeCanvas; return resizeCanvas;
} }


function doesOverlap(r1, r2, overlap) { function createCanvas (width, height) {
overlap = overlap || 0.5; if (typeof Canvas !== 'undefined') {

// have node-canvas
var overlapW, overlapH; return new Canvas(width, height);
if (r1.x > r2.x) {
overlapW = Math.min((r2.x + r2.width) - r1.x, r1.width);
}
else {
overlapW = Math.min((r1.x + r1.width) - r2.x, r2.width);
}

if (r1.y > r2.y) {
overlapH = Math.min((r2.y + r2.height) - r1.y, r1.height);
} }
else { else {
overlapH = Math.min((r1.y + r1.height) - r2.y, r2.height); // in browser
} var canvas = document.createElement('canvas');

canvas.setAttribute('width', width);
if (overlapW <= 0 || overlapH <= 0) { canvas.setAttribute('height', height);
return false; return canvas;
}
var intersect = overlapW * overlapH;
var union = (r1.width * r1.height) + (r2.width * r2.height) - (intersect * 2);

if (intersect / union > overlap) {
return true;
} }
return false;
} }




Expand Down
73 changes: 73 additions & 0 deletions nms.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,73 @@
/* non-maximum suppression - combine overlapping rects into the strongest one */

exports.combineOverlaps = combineOverlaps;

/* rects is an array of objects that look like:
* {
* x: // top left x coordinate,
* y: // lop left y coordinate,
* width: // width of rect,
* height: // height of rect,
* prob: // the higher, the more likely it will suppress other rects
* }
*
* minRatio is the min ratio of intersection area to union area of two rects
* to qualify them as overlapping.
*
* minOverlaps is the number of suppressions required for a rect
* to be included in the final returned set.
*/
function combineOverlaps(rects, minRatio, minOverlaps) {
console.log(minRatio, minOverlaps);
minRatio = minRatio || 0.5;
minOverlaps = minOverlaps || 1;

for (var i = 0; i < rects.length; i++) {
var r1 = rects[i];
r1.tally = 0; // number of rects it's suppressed

for (var j = 0; j < i; j++) {
var r2 = rects[j];

if (doesOverlap(r1, r2, minRatio)) {
if (r1.prob > r2.prob) {
r2.suppressed = true;
r1.tally += 1 + r2.tally;
}
else {
r1.suppressed = true;
r2.tally += 1 + r1.tally;
}
}
}
}
// only take a rect if it wasn't suppressed by any other rect
return rects.filter(function(rect) {
return !rect.suppressed && rect.tally >= minOverlaps;
})
}

function doesOverlap(r1, r2, minRatio) {
var overlapW, overlapH;
if (r1.x > r2.x) {
overlapW = Math.min((r2.x + r2.width) - r1.x, r1.width);
}
else {
overlapW = Math.min((r1.x + r1.width) - r2.x, r2.width);
}

if (r1.y > r2.y) {
overlapH = Math.min((r2.y + r2.height) - r1.y, r1.height);
}
else {
overlapH = Math.min((r1.y + r1.height) - r2.y, r2.height);
}

if (overlapW <= 0 || overlapH <= 0) {
return false;
}
var intersect = overlapW * overlapH;
var union = (r1.width * r1.height) + (r2.width * r2.height) - (intersect * 2);

return intersect / union > minRatio;
}

0 comments on commit 778d6fb

Please sign in to comment.