Skip to content

Commit

Permalink
More efficient PCA
Browse files Browse the repository at this point in the history
  • Loading branch information
altomani committed May 2, 2013
1 parent a62027d commit 468ff02
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Pulse JS

Use a webcam to measure heart rate. See demo at <http://pulsejs.github.io>
Use a webcam to measure heart rate. See demo at <http://altomani.github.io/PulseJS>

## TODO

Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ <h1>Charts</h1>
<div id="chart2" style="width:640px; height:480px"></div>

<p>Spectrum</p>
<div id="chart3" style="width:640px; height:480px"></div>
<div id="chart3" style="width:1920px; height:480px"></div>


</div>
Expand Down
24 changes: 12 additions & 12 deletions js/pulse.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function start() {
if (frame < 30) {
compatibility.requestAnimationFrame(tick);
++frame
} else if (frame < num_frames + 30 + 1) {
} else if (frame < num_frames + 30 + 3) {
var f = frame - 30;
compatibility.requestAnimationFrame(tick);
if (video.readyState === video.HAVE_ENOUGH_DATA) {
Expand All @@ -65,7 +65,7 @@ function start() {

++frame;
}
} else if (frame === num_frames + 30 + 1) {
} else if (frame === num_frames + 30 + 3) {
video.pause();
video.src=null;
findPulse();
Expand All @@ -78,25 +78,25 @@ function start() {
// Gaussian blur
var r = [], g = [], b = [];
for (i = 0; i < num_frames; i += 2) {
r[i/4] = red[i] + 3*red[i+1] + 3*red[i+2] + red[i+3];
g[i/4] = green[i] + 3*green[i+1] + 3*green[i+2] + green[i+3];
b[i/4] = blue[i] + 3*blue[i+1] + 3*blue[i+2] + blue[i+3];
r[i/2]=(red[i] + 3*red[i+1] + 3*red[i+2] + red[i+3]);
g[i/2]=(green[i] + 3*green[i+1] + 3*green[i+2] + green[i+3]);
b[i/2]=(blue[i] + 3*blue[i+1] + 3*blue[i+2] + blue[i+3]);
};

r = utils.normalize(r);
g = utils.normalize(g);
b = utils.normalize(b);
r = utils.normalize(utils.delinearize(r));
g = utils.normalize(utils.delinearize(g));
b = utils.normalize(utils.delinearize(b));

var signals = utils.PCA([r, g]);
var spectrum = utils.spectrum(signals[1]);
var spectrum = signals.map(utils.spectrum);

var pulse=0, max=0, i;

for (i=0; i<num_frames;i++) {
var frequency=(60.0/num_frames)*(i+0.5);
if (frequency>0.5 && frequency<3) {
if (spectrum[i]>max) {
max=spectrum[i];
if (spectrum[1][i]>max) {
max=spectrum[1][i];
pulse=Math.round(frequency*60);
}
}
Expand All @@ -110,7 +110,7 @@ function start() {

$.plot("#chart2", signals.map(utils.addIndex) );

$.plot("#chart3", [ utils.addIndex(spectrum.slice(0,64)) ]);
$.plot("#chart3", spectrum.map(utils.addIndex) );



Expand Down
24 changes: 20 additions & 4 deletions js/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var utils = (function utils() {});

utils.sum = function (arr) {
return arr.reduce( function(a, b) { return a + b; } );
var s = arr.reduce( function(a, b) { return a + b; } );
return s;
}

utils.mean = function (arr) {
Expand Down Expand Up @@ -34,8 +35,8 @@ utils.stdErr = function (arr) {
}

utils.normalize =function (arr) {
var s = utils.stdErr(arr)
return utils.center(arr).map( function (x) { return x / s } );
var s = utils.stdErr(arr);
return utils.center(arr).map( function (x) { return (x / s) } );
}

utils.covarAM = function (arr, mat) {
Expand All @@ -53,7 +54,7 @@ utils.covMatrix = function (mat) {
utils.SVD = numeric.svd;

utils.PCA = function (mat) {
return utils.dot(utils.SVD(numeric.transpose(mat)).V, mat);
return numeric.transpose(utils.SVD(numeric.transpose(mat)).U);
}

utils.spectrum = function (arr) {
Expand All @@ -68,4 +69,19 @@ utils.max = function (arr) {

utils.addIndex = function (arr) {
return arr.map(function (x, i) { return [i,x]; });
}

utils.range = function (n) {
var i, a = [];
for (i = 0; i < n; i++) {
a.push(i);
}
return a;
}

utils.delinearize = function (arr) {
var l=arr.length, r=utils.range(l),
beta = utils.covariance(arr, r)/utils.variance(r),
alpha = utils.mean(arr) - beta * utils.mean(r);
return arr.map(function(x, i) { return x-alpha-beta*i})
}

0 comments on commit 468ff02

Please sign in to comment.