From 456e42417631da02a688387adea7e835d9667d9c Mon Sep 17 00:00:00 2001 From: Cideck Date: Mon, 20 Nov 2023 11:27:11 +0100 Subject: [PATCH 01/10] prevent creation of default face tracker TFFaceMesh --- src/index.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.mjs b/src/index.mjs index b13ed27eb..c2010fefb 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -57,7 +57,9 @@ var eventTypes = ['click', 'move']; //movelistener timeout clock parameters var moveClock = performance.now(); //currently used tracker and regression models, defaults to clmtrackr and linear regression -var curTracker = new webgazer.tracker.TFFaceMesh(); +// xpln.ai 2023-11-19: Disable default TFFaceMesh tracker, because we use our own faceTracker! + +var curTracker = null; // new webgazer.tracker.TFFaceMesh(); var regs = [new webgazer.reg.RidgeReg()]; // var blinkDetector = new webgazer.BlinkDetector(); From 8388cc84f999e0ab6fdbea04c6ae7a8e36b0018a Mon Sep 17 00:00:00 2001 From: Cideck Date: Mon, 20 Nov 2023 11:31:34 +0100 Subject: [PATCH 02/10] npm run watch --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 9a04f8629..ed2fff8ce 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "clean": "rimraf dist", "prebuild": "npm run clean", "dev": "webpack --progress --config webpack.config.js --mode development", + "watch": "webpack --watch --progress --config webpack.config.js --mode development", "build": "webpack --progress --config webpack.config.js --mode production", "gen_docs": "jsdoc -c jsdoc.conf.json src/*" }, From 5196995097f423ec537e90ddd738e8fb43c1bfc8 Mon Sep 17 00:00:00 2001 From: Cideck Date: Mon, 20 Nov 2023 11:31:55 +0100 Subject: [PATCH 03/10] copy build file to our chrome extension --- webpack.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webpack.config.js b/webpack.config.js index e0c0d1129..b2fc0149a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -46,10 +46,14 @@ const varConfig = { events: { onEnd: { copy: [ + /* xpln.ai 2023-11-19: Disable useless copy to ./www/ { source: './dist/webgazer.js', destination: './www/' }, { source: './dist/webgazer.js.map', destination: './www/' }, { source: './dist/webgazer.js', destination: './www/data/src/' }, { source: './dist/webgazer.js.map', destination: './www/data/src/' }, + */ + // xpln.ai 2023-11-19: Instead we copy to our own chrome extension + { source: './dist/webgazer.js', destination: '../xpln.ai/scripts_crea/chrome_extension/ext/webgazer/webgazer.js', options: { overwrite: true } }, ], }, }, From d0cbe244103ae8c4a55f53c263057ecde3217b48 Mon Sep 17 00:00:00 2001 From: Cideck Date: Mon, 20 Nov 2023 11:38:42 +0100 Subject: [PATCH 04/10] comment --- src/index.mjs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/index.mjs b/src/index.mjs index c2010fefb..f3d0d7db4 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -57,9 +57,10 @@ var eventTypes = ['click', 'move']; //movelistener timeout clock parameters var moveClock = performance.now(); //currently used tracker and regression models, defaults to clmtrackr and linear regression -// xpln.ai 2023-11-19: Disable default TFFaceMesh tracker, because we use our own faceTracker! - -var curTracker = null; // new webgazer.tracker.TFFaceMesh(); +/* xpln.ai 2023-11-19: Disable default TFFaceMesh tracker, because we use our own faceTracker! +var curTracker = new webgazer.tracker.TFFaceMesh(); +*/ +var curTracker = null; // xpln.ai 2023-11-19 var regs = [new webgazer.reg.RidgeReg()]; // var blinkDetector = new webgazer.BlinkDetector(); From a6744208507e199617b8c2b4537b42db5db933cf Mon Sep 17 00:00:00 2001 From: Cideck Date: Mon, 27 Nov 2023 17:59:47 +0100 Subject: [PATCH 05/10] simply override data for ridge regression --- src/util.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util.mjs b/src/util.mjs index 18bbdaecb..80ac09773 100644 --- a/src/util.mjs +++ b/src/util.mjs @@ -37,7 +37,8 @@ util.getEyeFeats = function(eyes) { this.equalizeHistogram(gray, 5, hist); return hist; }; - + // xpln.ai 2023-11-27: simply override data for ridge regression + if (eyes.ridgeRegData) return eyes.ridgeRegData; if (webgazer.params.trackEye == 'left') { return process(eyes.left); } From 54aab106cbafe2316673535d3c3699a853e13f4c Mon Sep 17 00:00:00 2001 From: Cideck Date: Fri, 9 Feb 2024 09:25:49 +0100 Subject: [PATCH 06/10] support for adding more data to the ridge regression, on top of existing data --- src/util.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.mjs b/src/util.mjs index 80ac09773..6ff8c5cbe 100644 --- a/src/util.mjs +++ b/src/util.mjs @@ -46,7 +46,7 @@ util.getEyeFeats = function(eyes) { return process(eyes.right); } else { - return [].concat(process(eyes.left), process(eyes.right)); + return [].concat(process(eyes.left), process(eyes.right), eyes.ridgeRegExtra); } } From fc09a4c294d00887a41140641ebdd4e6554b4518 Mon Sep 17 00:00:00 2001 From: Cideck Date: Mon, 26 Feb 2024 21:41:13 +0100 Subject: [PATCH 07/10] normilize the features of the ridge regression --- src/util.mjs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/util.mjs b/src/util.mjs index 6ff8c5cbe..3c9b4c1ca 100644 --- a/src/util.mjs +++ b/src/util.mjs @@ -24,6 +24,20 @@ util.Eye = function(patch, imagex, imagey, width, height) { this.height = height; }; +// xpln.ai 2024-02-26: normalize pixel values between 0 and 1 +util.normalize = function(arr, digits) { + var min = Infinity, max = -Infinity, precision = Math.pow(10, digits); + for (var i=0, imax=arr.length; i arr[i]) min = arr[i]; + if (max < arr[i]) max = arr[i]; + } + var range = max - min; + if (!range) return; + for (var i=0, imax=arr.length; i Date: Tue, 25 Jun 2024 16:32:39 +0200 Subject: [PATCH 08/10] our own simpler faster ridge regression --- src/index.mjs | 2 ++ src/ridgeRegXpln.mjs | 82 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/ridgeRegXpln.mjs diff --git a/src/index.mjs b/src/index.mjs index f3d0d7db4..913da4e29 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -10,6 +10,7 @@ import TFFaceMesh from './facemesh.mjs'; import Reg from './ridgeReg.mjs'; import ridgeRegWeighted from './ridgeWeightedReg.mjs'; import ridgeRegThreaded from './ridgeRegThreaded.mjs'; +import RidgeRegXpln from './ridgeRegXpln.mjs'; import util from './util.mjs'; const webgazer = {}; @@ -18,6 +19,7 @@ webgazer.tracker.TFFaceMesh = TFFaceMesh; webgazer.reg = Reg; webgazer.reg.RidgeWeightedReg = ridgeRegWeighted.RidgeWeightedReg; webgazer.reg.RidgeRegThreaded = ridgeRegThreaded.RidgeRegThreaded; +webgazer.reg.RidgeRegXpln = RidgeRegXpln; webgazer.util = util; webgazer.params = params; diff --git a/src/ridgeRegXpln.mjs b/src/ridgeRegXpln.mjs new file mode 100644 index 000000000..2837821be --- /dev/null +++ b/src/ridgeRegXpln.mjs @@ -0,0 +1,82 @@ +import util from './util.mjs'; +import util_regression from './util_regression.mjs'; + +/** + * Constructor of RidgeRegXpln object, + * this object allow to perform ridge regression + * @constructor + */ +const RidgeRegXpln = function() { + this.init(); +}; + +/** + * Initialize new arrays and initialize Kalman filter. + */ +RidgeRegXpln.prototype.init = util_regression.InitRegression + +/** + * Add given data from eyes + * @param {Object} eyes - eyes where extract data to add + * @param {Object} screenPos - The current screen point + * @param {Object} type - The type of performed action + */ +RidgeRegXpln.prototype.addData = function(eyes, screenPos, type) { + util_regression.addData.call(this, eyes, screenPos, type); + delete this.xCoef; + delete this.yCoef; +}; + +/** + * Try to predict coordinates from pupil data + * after apply linear regression on data set + * @param {Object} features - The current user eyes features + * @returns {Object} + */ +RidgeRegXpln.prototype.predict = function(eyesObj) { + if (!eyesObj || this.eyeFeaturesClicks.length === 0) { + return null; + } + + var screenXArray = this.screenXClicksArray.data; + var screenYArray = this.screenYClicksArray.data; + var eyeFeatures = this.eyeFeaturesClicks.data; + + if (!this.xCoef) this.xCoef = util_regression.ridge(screenXArray, eyeFeatures, this.ridgeParameter); + if (!this.yCoef) this.yCoef = util_regression.ridge(screenYArray, eyeFeatures, this.ridgeParameter); + + var features = util.getEyeFeats(eyesObj); + var predictedX = 0; + for(var i=0; i< features.length; i++){ + predictedX += features[i] * this.xCoef[i]; + } + var predictedY = 0; + for(var i=0; i< features.length; i++){ + predictedY += features[i] * this.yCoef[i]; + } + + return { + x: Math.floor(predictedX), + y: Math.floor(predictedY) + }; +}; + +RidgeRegXpln.prototype.setData = function() { + throw new Error('Not implemented!!!'); +}; + +/** + * Return the data + * @returns {Array.|*} + */ +RidgeRegXpln.prototype.getData = function() { + throw new Error('Not implemented!!!'); +}; + +/** + * The RidgeRegXpln object name + * @type {string} + */ +RidgeRegXpln.prototype.name = 'ridgeXpln'; + +export default RidgeRegXpln; From c3920f4b275ecf83bf8fffefa8da134403985c3b Mon Sep 17 00:00:00 2001 From: Cideck Date: Wed, 26 Jun 2024 13:19:01 +0200 Subject: [PATCH 09/10] remove dependancy on getEyeFeats --- src/ridgeRegXpln.mjs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/ridgeRegXpln.mjs b/src/ridgeRegXpln.mjs index 2837821be..d43352b4a 100644 --- a/src/ridgeRegXpln.mjs +++ b/src/ridgeRegXpln.mjs @@ -16,25 +16,32 @@ const RidgeRegXpln = function() { RidgeRegXpln.prototype.init = util_regression.InitRegression /** - * Add given data from eyes - * @param {Object} eyes - eyes where extract data to add + * Add given data from features + * @param {Array} features - features where extract data to add * @param {Object} screenPos - The current screen point * @param {Object} type - The type of performed action */ -RidgeRegXpln.prototype.addData = function(eyes, screenPos, type) { - util_regression.addData.call(this, eyes, screenPos, type); - delete this.xCoef; - delete this.yCoef; +RidgeRegXpln.prototype.addData = function(features, screenPos, type) { + if (!features) return; + if (type === 'click') { + this.screenXClicksArray.push([screenPos[0]]); + this.screenYClicksArray.push([screenPos[1]]); + this.eyeFeaturesClicks.push(features); + delete this.xCoef; + delete this.yCoef; + } else if (type === 'move') { + throw new Error('Not implemented!!!'); + } }; /** * Try to predict coordinates from pupil data * after apply linear regression on data set - * @param {Object} features - The current user eyes features + * @param {Array} features - The current user features features * @returns {Object} */ -RidgeRegXpln.prototype.predict = function(eyesObj) { - if (!eyesObj || this.eyeFeaturesClicks.length === 0) { +RidgeRegXpln.prototype.predict = function(features) { + if (!features || this.eyeFeaturesClicks.length === 0) { return null; } @@ -45,7 +52,6 @@ RidgeRegXpln.prototype.predict = function(eyesObj) { if (!this.xCoef) this.xCoef = util_regression.ridge(screenXArray, eyeFeatures, this.ridgeParameter); if (!this.yCoef) this.yCoef = util_regression.ridge(screenYArray, eyeFeatures, this.ridgeParameter); - var features = util.getEyeFeats(eyesObj); var predictedX = 0; for(var i=0; i< features.length; i++){ predictedX += features[i] * this.xCoef[i]; From 8b8b84e0a312b1e7c92ebb598b870ee9580238ec Mon Sep 17 00:00:00 2001 From: Cideck Date: Wed, 26 Jun 2024 13:39:05 +0200 Subject: [PATCH 10/10] simplify RidgeRegXpln --- src/ridgeRegXpln.mjs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/ridgeRegXpln.mjs b/src/ridgeRegXpln.mjs index d43352b4a..57a685cbf 100644 --- a/src/ridgeRegXpln.mjs +++ b/src/ridgeRegXpln.mjs @@ -45,20 +45,19 @@ RidgeRegXpln.prototype.predict = function(features) { return null; } - var screenXArray = this.screenXClicksArray.data; - var screenYArray = this.screenYClicksArray.data; - var eyeFeatures = this.eyeFeaturesClicks.data; - - if (!this.xCoef) this.xCoef = util_regression.ridge(screenXArray, eyeFeatures, this.ridgeParameter); - if (!this.yCoef) this.yCoef = util_regression.ridge(screenYArray, eyeFeatures, this.ridgeParameter); - - var predictedX = 0; - for(var i=0; i< features.length; i++){ - predictedX += features[i] * this.xCoef[i]; + if (!this.xCoef || !this.yCoef) { + var screenXArray = this.screenXClicksArray.data; + var screenYArray = this.screenYClicksArray.data; + var eyeFeatures = this.eyeFeaturesClicks.data; + this.xCoef = util_regression.ridge(screenXArray, eyeFeatures, this.ridgeParameter); + this.yCoef = util_regression.ridge(screenYArray, eyeFeatures, this.ridgeParameter); } - var predictedY = 0; - for(var i=0; i< features.length; i++){ - predictedY += features[i] * this.yCoef[i]; + + var predictedX = 0, predictedY = 0, cx = this.xCoef, cy = this.yCoef; + for(var i=0; i< features.length; i++) { + var f = features[i]; + predictedX += f * cx[i]; + predictedY += f * cy[i]; } return {