Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit cb7f762
Showing
11 changed files
with
525 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# hog-descriptor | ||
hog-descriptor extracts a [Histogram of Oriented Gradients](http://en.wikipedia.org/wiki/Histogram_of_oriented_gradients) descriptor from an image (canvas): | ||
|
||
```javascript | ||
var hog = require("hog-descriptor"); | ||
|
||
var descriptor = hog.extractHOG(canvas); | ||
|
||
console.log(descriptor); // [0.455, 0.003, 0.987, ...] | ||
``` | ||
|
||
# Install | ||
|
||
For node.js: | ||
|
||
```bash | ||
npm install hog-descriptor | ||
``` | ||
|
||
# API | ||
|
||
`extractHOG()` takes options for the cell size (default is 6 pixels), block size (default is 2 cells), number of bins per orientation histogram (default is 6), and block normalization method (one of `"L1"` (default), `"L1-sqrt"`, and `"L2"`): | ||
|
||
```javascript | ||
var options = { | ||
cellSize: 6, // length of cell in px | ||
blockSize: 2, // length of block in number of cells | ||
bins: 6, // bins per histogram | ||
norm: 'L1' // block normalization method | ||
} | ||
|
||
var descriptor = hog.extractHOG(canvas, options); | ||
``` | ||
|
||
# Other Goodies | ||
|
||
In the process of computing a HOG descriptor, a bunch of other intermediate things have to be computed, like the image gradient, so these steps are also provided as secret goodies on the library: | ||
|
||
#### intensities | ||
|
||
Get a 2d array of the pixel intensities (normalized to fall between `0` and `1`): | ||
|
||
```javascript | ||
var intensities = hog.intensities(canvas); | ||
``` | ||
|
||
The return array is indexed first by row (y direction) then by column (x direction). | ||
|
||
#### gradients | ||
|
||
Get a 2d array of the image gradient at each pixel of the canvas with respect to the vertical and horizontal directions using a `[-1, 0, 1]` filter: | ||
|
||
```javascript | ||
var gradients = hog.gradients(canvas); | ||
``` | ||
|
||
Return looks like this: | ||
|
||
```javascript | ||
{ | ||
x: [[0.0084, 0.354] /* , ... */], | ||
y: [[0.056, 0.7888] /* , ... */] | ||
} | ||
``` | ||
|
||
#### gradientVectors | ||
|
||
Get a 2d array of the gradient vectors at each pixel of the canvas: | ||
|
||
```javascript | ||
var vectors = hog.gradientVectors(canvas); | ||
``` | ||
|
||
Return value is the vector at each pixel with `mag` and `orient` for magnitude and orientation (in radians): | ||
|
||
```javascript | ||
[[{ mag: 0.4, orient: -1.52} /*, ... */]] | ||
``` | ||
|
||
#### drawGreyscale | ||
|
||
Greyscales a canvas: | ||
|
||
```javascript | ||
hog.drawGreyscale(canvas) | ||
``` | ||
![x-gradient](https://raw.github.com/harthur/hog-descriptor/master/test/greyscale.jpg) | ||
|
||
#### drawGradient | ||
|
||
Draws the gradient of the canvas with respect to 'x' or 'y' direction: | ||
|
||
```javascript | ||
hog.drawGradient(canvas, 'x') | ||
``` | ||
|
||
![x-gradient](https://raw.github.com/harthur/hog-descriptor/master/test/gradient-x.jpg) | ||
|
||
```javascript | ||
hog.drawGradient(canvas, 'y') | ||
``` | ||
|
||
![y-gradient](https://raw.github.com/harthur/hog-descriptor/master/test/gradient-y.jpg) | ||
|
||
#### drawMagnitude | ||
|
||
Draws the magnitude of the gradient vectors over the canvas: | ||
|
||
```javascript | ||
hog.drawMagnitude(canvas) | ||
``` | ||
|
||
![magnitude](https://raw.github.com/harthur/hog-descriptor/master/test/magnitude.jpg) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
var _ = require("underscore"), | ||
processing = require("./processing"), | ||
norms = require("./norms"); | ||
|
||
_(module.exports).extend(processing); | ||
|
||
exports.extractHOG = function(canvas, options) { | ||
options = options || {}; | ||
var cellSize = options.cellSize || 6; | ||
var blockSize = options.blockSize || 2; | ||
var bins = options.bins || 6; | ||
var normalize = norms[options.norm || "L1"]; | ||
|
||
var vectors = processing.gradientVectors(canvas); | ||
|
||
var cellsWide = Math.floor(canvas.width / cellSize); | ||
var cellsHigh = Math.floor(canvas.height / cellSize); | ||
var histograms = new Array(cellsHigh); | ||
|
||
for (var i = 0; i < cellsHigh; i++) { | ||
histograms[i] = new Array(cellsWide); | ||
|
||
for (var j = 0; j < cellsWide; j++) { | ||
var cell = getSquare(vectors, j * cellSize, i * cellSize, cellSize); | ||
histograms[i][j] = getHistogram(cell, bins); | ||
} | ||
} | ||
var blocks = getNormalizedBlocks(histograms, blockSize, normalize); | ||
return _(blocks).flatten(); | ||
} | ||
|
||
function getNormalizedBlocks(histograms, blockSize, normalize) { | ||
var blocks = []; | ||
var blocksHigh = histograms.length - blockSize + 1; | ||
var blocksWide = histograms[0].length - blockSize + 1; | ||
|
||
for (var y = 0; y < blocksHigh; y++) { | ||
for (var x = 0; x < blocksWide; x++) { | ||
var block = getBlock(histograms, x, y, blockSize); | ||
normalize(block); | ||
blocks.push(block); | ||
} | ||
} | ||
return blocks; | ||
} | ||
|
||
function getBlock(matrix, x, y, length) { | ||
var square = []; | ||
for (var i = y; i < y + length; i++) { | ||
var row = matrix[i]; | ||
for (var j = x; j < x + length; j++) { | ||
square.push(row[j]); | ||
} | ||
} | ||
return _(square).flatten(); | ||
} | ||
|
||
|
||
function getHistogram(cell, bins) { | ||
var histogram = zeros(bins); | ||
var size = cell.length; | ||
|
||
for (var i = 0; i < size; i++) { | ||
for (var j = 0; j < size; j++) { | ||
var vector = cell[i][j]; | ||
var bin = binFor(vector.orient, bins); | ||
histogram[bin] += vector.mag; | ||
} | ||
} | ||
return histogram; | ||
} | ||
|
||
function getSquare(elements, x, y, size) { | ||
var square = new Array(size); | ||
|
||
for (var i = 0; i < size; i++) { | ||
square[i] = new Array(size); | ||
|
||
for (var j = 0; j < size; j++) { | ||
square[i][j] = elements[y + i][x + j]; | ||
} | ||
} | ||
return square; | ||
} | ||
|
||
function binFor(radians, bins) { | ||
var angle = radians * (180 / Math.PI); | ||
if (angle < 0) { | ||
angle += 180; | ||
} | ||
var bin = Math.floor(angle / 181 * bins); | ||
return bin; | ||
} | ||
|
||
function zeros(size) { | ||
var array = new Array(size); | ||
for (var i = 0; i < size; i++) { | ||
array[i] = 0; | ||
} | ||
return array; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
var epsilon = 0.00001; | ||
|
||
module.exports = { | ||
L1: function(vector) { | ||
var norm = 0; | ||
for (var i = 0; i < vector.length; i++) { | ||
norm += Math.abs(vector[i]); | ||
} | ||
var denom = norm + epsilon; | ||
|
||
for (var i = 0; i < vector.length; i++) { | ||
vector[i] /= denom; | ||
} | ||
}, | ||
|
||
'L1-sqrt': function(vector) { | ||
var norm = 0; | ||
for (var i = 0; i < vector.length; i++) { | ||
norm += Math.abs(vector[i]); | ||
} | ||
var denom = norm + epsilon; | ||
|
||
for (var i = 0; i < vector.length; i++) { | ||
vector[i] = Math.sqrt(vector[i] / denom); | ||
} | ||
}, | ||
|
||
L2: function(vector) { | ||
var sum = 0; | ||
for (var i = 0; i < vector.length; i++) { | ||
sum += Math.pow(vector[i], 2); | ||
} | ||
var denom = Math.sqrt(sum + epsilon); | ||
for (var i = 0; i < vector.length; i++) { | ||
vector[i] /= denom; | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "hog-descriptor", | ||
"description": "Histogram of Oriented Gradients (HOG) descriptor extractor", | ||
"version": "0.1.0", | ||
"author": "Heather Arthur <fayearthur@gmail.com>", | ||
"main": "./hog", | ||
"repository": { | ||
"type": "git", | ||
"url": "http://github.com/harthur/hog-descriptor.git" | ||
}, | ||
"dependencies": { | ||
"underscore" : "*" | ||
}, | ||
"keywords": ["image processing", "computer vision"] | ||
} |
Oops, something went wrong.