Skip to content

Commit

Permalink
Added a gaze prediction
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander James Wallar committed Jul 29, 2013
1 parent 4cfe457 commit 954c637
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 79 deletions.
154 changes: 85 additions & 69 deletions js/camgaze.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ camgaze.Camgaze.prototype.setFrameOperator = function (callback) {
self.video,
canvasDrawer
);
canvasDrawer.drawAll();
canvasDrawer.drawAll(false);
} else {
var img = callback(frame, self.video);
if (img.cols != undefined) {
Expand All @@ -122,10 +122,16 @@ camgaze.Camgaze.prototype.setFrameOperator = function (callback) {
//
//////////////////////////////////////////////////////////////

// relative position on face
camgaze.constants.LEFT = 1;
camgaze.constants.RIGHT = 2;
camgaze.constants.NOT_IN_FACE = 0;

// eye proportions with regard to the face
camgaze.constants.RIGHT_PROP_WIDTH = 0.21;
camgaze.constants.LEFT_PROP_WIDTH = 0.54;
camgaze.constants.PROP_HEIGHT = 0.37;

//////////////////////////////////////////////////////////////
//
// util
Expand Down Expand Up @@ -1043,6 +1049,7 @@ camgaze.EyeData = function (eyeRect) {
this.maxColor = undefined;
this.minColor = undefined;
this.face = undefined;
this.eyeCenter = undefined;
}

camgaze.EyeData.prototype = {
Expand Down Expand Up @@ -1076,82 +1083,91 @@ camgaze.EyeData.prototype = {
},

inProportionRange : function (xProp, yProp) {
return (
this.eyeRect.x >= this.getFace().x + (

var cPoint = new camgaze.structures.Point(
this.getFace().x + (
this.getFace().width * xProp
) &&
this.eyeRect.x <= this.getFace().x + (
this.getFace().width * xProp +
this.eyeRect.width
) &&
this.eyeRect.y >= this.getFace().y + (
) + this.eyeRect.width / 2,

this.getFace().y + (
this.getFace().height * yProp
) &&
this.eyeRect.y <= this.getFace().y + (
this.getFace().height * yProp +
this.eyeRect.height
)
);
return (
cPoint.distTo(this.getScaledCentroid()) <
this.eyeRect.width / 2
);
},

/*
Determines the which eye (left or right) is the
one depicted in this structure. Also sets the
eye center which is later used to determine the
gaze. These properties are derived by the
statistical proportions of the face and therefore
can become inaccurate. More testing is needed
*/
determineSide : function () {
if (this.inProportionRange(0.21, 0.37)) {
if (
this.inProportionRange(
camgaze.constants.RIGHT_PROP_WIDTH,
camgaze.constants.PROP_HEIGHT
)
) {
this.faceSide = camgaze.constants.RIGHT;
} else if (this.inProportionRange(0.54, 0.37)) {
this.eyeCenter = new camgaze.structures.Point(
this.getFace().x +
(
this.getFace().width *
camgaze.constants.RIGHT_PROP_WIDTH
) +
this.eyeRect.width / 2,
this.getFace().y +
(
this.getFace().height *
camgaze.constants.PROP_HEIGHT
)
);
} else if (
this.inProportionRange(
camgaze.constants.LEFT_PROP_WIDTH,
camgaze.constants.PROP_HEIGHT
)
) {
this.faceSide = camgaze.constants.LEFT;
this.eyeCenter = new camgaze.structures.Point(
this.getFace().x +
(
this.getFace().width *
camgaze.constants.LEFT_PROP_WIDTH
) +
this.eyeRect.width / 2,
this.getFace().y +
(
this.getFace().height *
camgaze.constants.PROP_HEIGHT
)
);
} else {
this.faceSide = camgaze.constants.NOT_IN_FACE;
this.eyeCenter = new camgaze.structures.Point(0, 0);
}

return this;
},

getFace : function () {
return this.face;
},

/*
Returns the vectors from the corners of
the image with reference to the sub
eye image.
*/
getCornerVectors : function () {
var pb = this.pupil;
var centroid = pb.getCentroid();
return {
topLeft : new camgaze.structures.Point(
centroid.x,
centroid.y
),
topRight : new camgaze.structures.Point(
centroid.x - this.eyeRect.width,
centroid.y
),
bottomLeft : new camgaze.structures.Point(
centroid.x,
centroid.y - this.eyeRect.height
),
bottomRight : new camgaze.structures.Point(
centroid.x - this.eyeRect.width,
centroid.y - this.eyeRect.height
)
}
},

/*
Returns the resultant vector from all of the
corners to the centroid point.
*/
getResultantVector : function () {
/*
var cVecs = this.getCornerVectors();
var resVec = new camgaze.structures.Point(0, 0);
for (var k in cVecs) {
//console.log(resVec);
resVec = resVec.add(cVecs[k]);
}
return resVec;
*/
var hc = this.getHaarCentroid();
return this.pupil.getCentroid().sub(hc).mult(4);
return this.getScaledCentroid().sub(
this.eyeCenter
).mult(3);
},

getMinMaxColors : function () {
Expand Down Expand Up @@ -1240,7 +1256,7 @@ camgaze.EyeTracker = function (xSize, ySize) {

this.previousEyes = new Array();
this.lostEyes = new camgaze.structures.Set(
camgaze.eyeHashFunc
camgaze.util.eyeHashFunc
);

this.resizeCanvas = document.createElement("canvas");
Expand Down Expand Up @@ -1519,18 +1535,6 @@ camgaze.EyeTracker.prototype = {
function (rect) {
if (Math.abs(rect.confidence) > 0.07) {
var eyeData = new camgaze.EyeData(rect);
faceRects.forEach(
function (fRect) {
if (
rect.x >= fRect.x &&
rect.x <= fRect.x + fRect.width &&
rect.y >= fRect.y &&
rect.y <= fRect.y + fRect.width
) {
eyeData.setFace(fRect);
}
}
);

// needs to use another canvas because
// stupid html5....
Expand All @@ -1548,6 +1552,18 @@ camgaze.EyeTracker.prototype = {
var minColor = pupilObj.minColor;
eyeData.setPupil(pupil);
eyeData.setMinMaxColor(minColor, maxColor);
faceRects.forEach(
function (fRect) {
if (
rect.x >= fRect.x &&
rect.x <= fRect.x + fRect.width &&
rect.y >= fRect.y &&
rect.y <= fRect.y + fRect.width
) {
eyeData.setFace(fRect);
}
}
);
trackingData.pushEye(eyeData);
}
}
Expand Down Expand Up @@ -1578,7 +1594,7 @@ camgaze.EyeTracker.prototype = {
//////////////////////////////////////////////////////////////

camgaze.EyeFilter = function () {
this.movAvgLength = 20;
this.movAvgLength = 5;
this.movAvgDict = {};
this.MovingAveragePoints = camgaze.structures.MovingAveragePoints;
this.origin = new camgaze.structures.Point(0, 0);
Expand Down Expand Up @@ -1624,7 +1640,7 @@ camgaze.EyeFilter.prototype = {

centroidMA :
new self.MovingAveragePoints(
eye.getPupil().getCentroid(),
eye.getScaledCentroid(),
self.movAvgLength
),

Expand Down
34 changes: 24 additions & 10 deletions js/eye_tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ window.onload = function () {

var frameOp = function (image_data, video, drawer) {
trackingData = eyeTracker.track(image_data, video);
//console.log(trackingData);
var gazeList = eyeFilter.getFilteredGaze(trackingData);
if (trackingData.eyeList.length > 0) {
drawer.clearAll();
gazeList.forEach(
function (eye) {
// draws the face circle
drawer.drawCircle(
{
x : eye.eyeData.getFace().x + eye.eyeData.getFace().width / 2,
y : eye.eyeData.getFace().y + eye.eyeData.getFace().height / 2
x : (
eye.eyeData.getFace().x +
eye.eyeData.getFace().width / 2
),
y : (
eye.eyeData.getFace().y +
eye.eyeData.getFace().height / 2
)
},
eye.eyeData.getFace().width / 2,
2,
Expand Down Expand Up @@ -70,14 +78,6 @@ window.onload = function () {
"red"
);

// draws the pupil
drawer.drawCircle(
eye.centroid.unfiltered,
4, // radius
-1, // line width (filled)
"red"
);

// draws the first nose line
drawer.drawLine(
{
Expand Down Expand Up @@ -198,6 +198,20 @@ window.onload = function () {
"red"
);

drawer.drawLine(
eye.centroid.filtered,
eye.centroid.filtered.add(eye.gazeVector),
2,
"green"
);

// draws the pupil
drawer.drawCircle(
eye.centroid.filtered,
4, // radius
-1, // line width (filled)
"red"
);
}
);
}
Expand Down

0 comments on commit 954c637

Please sign in to comment.