remote-calibrator 0.2.2-beta.5 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +4 -1
- package/lib/RemoteCalibrator.min.js +1 -1
- package/lib/RemoteCalibrator.min.js.LICENSE.txt +1 -1
- package/lib/RemoteCalibrator.min.js.map +1 -1
- package/media/measureDistance.png +0 -0
- package/media/panel.png +0 -0
- package/media/screenSize.png +0 -0
- package/media/trackGaze.png +0 -0
- package/package.json +4 -4
- package/src/WebGazer4RC/.gitattributes +0 -10
- package/src/WebGazer4RC/LICENSE.md +0 -15
- package/src/WebGazer4RC/README.md +0 -142
- package/src/WebGazer4RC/gnu-lgpl-v3.0.md +0 -163
- package/src/WebGazer4RC/gplv3.md +0 -636
- package/src/WebGazer4RC/package-lock.json +0 -1133
- package/src/WebGazer4RC/package.json +0 -28
- package/src/WebGazer4RC/src/dom_util.mjs +0 -27
- package/src/WebGazer4RC/src/facemesh.mjs +0 -150
- package/src/WebGazer4RC/src/index.mjs +0 -1213
- package/src/WebGazer4RC/src/mat.mjs +0 -301
- package/src/WebGazer4RC/src/params.mjs +0 -29
- package/src/WebGazer4RC/src/pupil.mjs +0 -109
- package/src/WebGazer4RC/src/ridgeReg.mjs +0 -104
- package/src/WebGazer4RC/src/ridgeRegThreaded.mjs +0 -161
- package/src/WebGazer4RC/src/ridgeWeightedReg.mjs +0 -125
- package/src/WebGazer4RC/src/ridgeWorker.mjs +0 -135
- package/src/WebGazer4RC/src/util.mjs +0 -348
- package/src/WebGazer4RC/src/util_regression.mjs +0 -240
- package/src/WebGazer4RC/src/worker_scripts/mat.js +0 -306
- package/src/WebGazer4RC/src/worker_scripts/util.js +0 -398
- package/src/WebGazer4RC/test/regression_test.js +0 -182
- package/src/WebGazer4RC/test/run_tests_and_server.sh +0 -24
- package/src/WebGazer4RC/test/util_test.js +0 -60
- package/src/WebGazer4RC/test/webgazerExtract_test.js +0 -40
- package/src/WebGazer4RC/test/webgazer_test.js +0 -160
- package/src/WebGazer4RC/test/www_page_test.js +0 -41
@@ -1,28 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"name": "webgazer",
|
3
|
-
"version": "2.1.0",
|
4
|
-
"private": "true",
|
5
|
-
"repository": {
|
6
|
-
"type": "git",
|
7
|
-
"url": "https://github.com/brownhci/WebGazer.git"
|
8
|
-
},
|
9
|
-
"license": "GPL-3.0-or-later",
|
10
|
-
"main": "dist/webgazer.js",
|
11
|
-
"module": "src/index.mjs",
|
12
|
-
"files": [
|
13
|
-
"/dist",
|
14
|
-
"/src"
|
15
|
-
],
|
16
|
-
"keywords": [
|
17
|
-
"webgazer",
|
18
|
-
"eyetracking",
|
19
|
-
"webcam"
|
20
|
-
],
|
21
|
-
"dependencies": {
|
22
|
-
"@tensorflow-models/facemesh": "^0.0.5",
|
23
|
-
"@tensorflow/tfjs": "^3.8.0",
|
24
|
-
"localforage": "^1.9.0",
|
25
|
-
"numeric": "1.2.6",
|
26
|
-
"regression": "2.0.1"
|
27
|
-
}
|
28
|
-
}
|
@@ -1,27 +0,0 @@
|
|
1
|
-
// helper functions
|
2
|
-
|
3
|
-
/**
|
4
|
-
* Provides requestAnimationFrame in a cross browser way.
|
5
|
-
*/
|
6
|
-
window.requestAnimFrame = (function() {
|
7
|
-
return window.requestAnimationFrame ||
|
8
|
-
window.webkitRequestAnimationFrame ||
|
9
|
-
window.mozRequestAnimationFrame ||
|
10
|
-
window.oRequestAnimationFrame ||
|
11
|
-
window.msRequestAnimationFrame ||
|
12
|
-
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
|
13
|
-
return window.setTimeout(callback, 1000/60);
|
14
|
-
};
|
15
|
-
})();
|
16
|
-
|
17
|
-
/**
|
18
|
-
* Provides cancelRequestAnimationFrame in a cross browser way.
|
19
|
-
*/
|
20
|
-
window.cancelRequestAnimFrame = (function() {
|
21
|
-
return window.cancelCancelRequestAnimationFrame ||
|
22
|
-
window.webkitCancelRequestAnimationFrame ||
|
23
|
-
window.mozCancelRequestAnimationFrame ||
|
24
|
-
window.oCancelRequestAnimationFrame ||
|
25
|
-
window.msCancelRequestAnimationFrame ||
|
26
|
-
window.clearTimeout;
|
27
|
-
})();
|
@@ -1,150 +0,0 @@
|
|
1
|
-
const FacemeshModel = require('@tensorflow-models/facemesh');
|
2
|
-
/**
|
3
|
-
* Constructor of TFFaceMesh object
|
4
|
-
* @constructor
|
5
|
-
* */
|
6
|
-
const TFFaceMesh = function() {
|
7
|
-
//Backend options are webgl, wasm, and CPU.
|
8
|
-
//For recent laptops WASM is better than WebGL.
|
9
|
-
//TODO: This hack makes loading the model block the UI. We should fix that
|
10
|
-
// this.model = (async () => { return await facemesh.load({"maxFaces":1}) })();
|
11
|
-
this.model = FacemeshModel.load({ "maxFaces": 1 });
|
12
|
-
this.predictionReady = false;
|
13
|
-
};
|
14
|
-
|
15
|
-
// Global variable for face landmark positions array
|
16
|
-
TFFaceMesh.prototype.positionsArray = null;
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Isolates the two patches that correspond to the user's eyes
|
20
|
-
* @param {Canvas} imageCanvas - canvas corresponding to the webcam stream
|
21
|
-
* @param {Number} width - of imageCanvas
|
22
|
-
* @param {Number} height - of imageCanvas
|
23
|
-
* @return {Object} the two eye-patches, first left, then right eye
|
24
|
-
*/
|
25
|
-
TFFaceMesh.prototype.getEyePatches = async function(imageCanvas, width, height) {
|
26
|
-
|
27
|
-
if (imageCanvas.width === 0) {
|
28
|
-
return null;
|
29
|
-
}
|
30
|
-
|
31
|
-
// Load the MediaPipe facemesh model.
|
32
|
-
const model = await this.model;
|
33
|
-
|
34
|
-
// Pass in a video stream (or an image, canvas, or 3D tensor) to obtain an
|
35
|
-
// array of detected faces from the MediaPipe graph.
|
36
|
-
const predictions = await model.estimateFaces(imageCanvas);
|
37
|
-
|
38
|
-
if (predictions.length == 0){
|
39
|
-
return false;
|
40
|
-
}
|
41
|
-
|
42
|
-
// Save positions to global variable
|
43
|
-
this.positionsArray = predictions[0].scaledMesh;
|
44
|
-
const positions = this.positionsArray;
|
45
|
-
|
46
|
-
// Fit the detected eye in a rectangle. [20200626 xk] not clear which approach is better
|
47
|
-
// https://raw.githubusercontent.com/tensorflow/tfjs-models/master/facemesh/mesh_map.jpg
|
48
|
-
|
49
|
-
// // Maintains a relatively stable shape of the bounding box at the cost of cutting off parts of
|
50
|
-
// // the eye when the eye is tilted.
|
51
|
-
// var leftOriginX = Math.round(positions[130][0]);
|
52
|
-
// var leftOriginY = Math.round(positions[27][1]);
|
53
|
-
// var leftWidth = Math.round(positions[243][0] - leftOriginX);
|
54
|
-
// var leftHeight = Math.round(positions[23][1] - leftOriginY);
|
55
|
-
// var rightOriginX = Math.round(positions[463][0]);
|
56
|
-
// var rightOriginY = Math.round(positions[257][1]);
|
57
|
-
// var rightWidth = Math.round(positions[359][0] - rightOriginX);
|
58
|
-
// var rightHeight = Math.round(positions[253][1] - rightOriginY);
|
59
|
-
|
60
|
-
// Won't really cut off any parts of the eye, at the cost of warping the shape (i.e. height/
|
61
|
-
// width ratio) of the bounding box.
|
62
|
-
var leftOriginX = Math.round(Math.min(positions[247][0], positions[130][0], positions[25][0]));
|
63
|
-
var leftOriginY = Math.round(Math.min(positions[247][1], positions[27][1], positions[190][1]));
|
64
|
-
var leftWidth = Math.round(Math.max(positions[190][0], positions[243][0], positions[233][0]) - leftOriginX);
|
65
|
-
var leftHeight = Math.round(Math.max(positions[25][1], positions[23][1], positions[112][1]) - leftOriginY);
|
66
|
-
var rightOriginX = Math.round(Math.min(positions[414][0], positions[463][0], positions[453][0]));
|
67
|
-
var rightOriginY = Math.round(Math.min(positions[414][1], positions[257][1], positions[467][1]));
|
68
|
-
var rightWidth = Math.round(Math.max(positions[467][0], positions[359][0], positions[255][0]) - rightOriginX);
|
69
|
-
var rightHeight = Math.round(Math.max(positions[341][1], positions[253][1], positions[255][1]) - rightOriginY);
|
70
|
-
|
71
|
-
if (leftWidth === 0 || rightWidth === 0){
|
72
|
-
console.log('an eye patch had zero width');
|
73
|
-
return null;
|
74
|
-
}
|
75
|
-
|
76
|
-
if (leftHeight === 0 || rightHeight === 0){
|
77
|
-
console.log('an eye patch had zero height');
|
78
|
-
return null;
|
79
|
-
}
|
80
|
-
|
81
|
-
// Start building object to be returned
|
82
|
-
var eyeObjs = {};
|
83
|
-
|
84
|
-
var leftImageData = imageCanvas.getContext('2d').getImageData(leftOriginX, leftOriginY, leftWidth, leftHeight);
|
85
|
-
eyeObjs.left = {
|
86
|
-
patch: leftImageData,
|
87
|
-
imagex: leftOriginX,
|
88
|
-
imagey: leftOriginY,
|
89
|
-
width: leftWidth,
|
90
|
-
height: leftHeight
|
91
|
-
};
|
92
|
-
|
93
|
-
var rightImageData = imageCanvas.getContext('2d').getImageData(rightOriginX, rightOriginY, rightWidth, rightHeight);
|
94
|
-
eyeObjs.right = {
|
95
|
-
patch: rightImageData,
|
96
|
-
imagex: rightOriginX,
|
97
|
-
imagey: rightOriginY,
|
98
|
-
width: rightWidth,
|
99
|
-
height: rightHeight
|
100
|
-
};
|
101
|
-
|
102
|
-
this.predictionReady = true;
|
103
|
-
|
104
|
-
return eyeObjs;
|
105
|
-
};
|
106
|
-
|
107
|
-
/**
|
108
|
-
* Returns the positions array corresponding to the last call to getEyePatches.
|
109
|
-
* Requires that getEyePatches() was called previously, else returns null.
|
110
|
-
*/
|
111
|
-
TFFaceMesh.prototype.getPositions = function () {
|
112
|
-
return this.positionsArray;
|
113
|
-
}
|
114
|
-
|
115
|
-
/**
|
116
|
-
* Reset the tracker to default values
|
117
|
-
*/
|
118
|
-
TFFaceMesh.prototype.reset = function(){
|
119
|
-
console.log( "Unimplemented; Tracking.js has no obvious reset function" );
|
120
|
-
}
|
121
|
-
|
122
|
-
/**
|
123
|
-
* Draw TF_FaceMesh_Overlay
|
124
|
-
*/
|
125
|
-
TFFaceMesh.prototype.drawFaceOverlay= function(ctx, keypoints){
|
126
|
-
// If keypoints is falsy, don't do anything
|
127
|
-
if (keypoints) {
|
128
|
-
ctx.fillStyle = '#32EEDB';
|
129
|
-
ctx.strokeStyle = '#32EEDB';
|
130
|
-
ctx.lineWidth = 0.5;
|
131
|
-
|
132
|
-
for (let i = 0; i < keypoints.length; i++) {
|
133
|
-
const x = keypoints[i][0];
|
134
|
-
const y = keypoints[i][1];
|
135
|
-
|
136
|
-
ctx.beginPath();
|
137
|
-
ctx.arc(x, y, 1 /* radius */, 0, 2 * Math.PI);
|
138
|
-
ctx.closePath();
|
139
|
-
ctx.fill();
|
140
|
-
}
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
|
-
/**
|
145
|
-
* The TFFaceMesh object name
|
146
|
-
* @type {string}
|
147
|
-
*/
|
148
|
-
TFFaceMesh.prototype.name = 'TFFaceMesh';
|
149
|
-
|
150
|
-
export default TFFaceMesh;
|