Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference to global webgazer object in utils.mjs #304

Open
fredcallaway opened this issue May 19, 2023 · 8 comments · Fixed by #317
Open

Reference to global webgazer object in utils.mjs #304

fredcallaway opened this issue May 19, 2023 · 8 comments · Fixed by #317

Comments

@fredcallaway
Copy link

Copy of #296 (seems to have been closed without a fix).

I'm using ES6 modules (import webgazer).

Uncaught (in promise) ReferenceError: webgazer is not defined
    at util.getEyeFeats (util.mjs:42:5)
    at util_regression.addData (util_regression.mjs:221:42)
    at util_regression.setData (util_regression.mjs:184:10)
    at loadGlobalData (index.mjs:436:15)
@jeffhuang
Copy link
Contributor

I'm traveling and not able to test this right now, but what about importing the default module

import webgazer from 'webgazer'

@fredcallaway
Copy link
Author

Yup, adding that line to utils.mjs fixes it!

@jeffhuang
Copy link
Contributor

Great, if you could submit a PR, I'll take a look when I'm back home

@fredcallaway
Copy link
Author

Given the simplicity of the fix, I think it makes more sense for an existing contributor (with a fork) to make this change.

@jeffhuang
Copy link
Contributor

@Skylion007 the import webgazer from 'webgazer' line breaks the webpack build npm run build because well, it doesn't exist when it's building. Any idea of the usual workaround, so that it can also be imported?

@Bmastaz
Copy link

Bmastaz commented Oct 23, 2023

any update ?

@jeffhuang
Copy link
Contributor

@Bmastaz the fix doesn't work (see my message above), so there isn't a good solution right now. If anyone proposes a solution, we can consider it, but right now this is still an open issue.

@dev-vinicius-andrade
Copy link

dev-vinicius-andrade commented Mar 27, 2024

I know that it's not ideal, currently I'm trying to implement it in a angular app with Typescript.

I apologize in advance if I can't be clear enougth explaining.

So, I've created a composable which is basically a wrapper to override the getEyeFeats method inside util.

import { WebGazer, WebGazerParams } from 'webgazer';

export async function useWebgazer(
  params: Partial<WebGazerParams> = {}
): Promise<WebGazer> {
  const webgazer = (await import('webgazer')).default;
  const resizeWidth = 10;
  const resizeHeight = 6;
  webgazer.util.getEyeFeats = (eyes: any) => {
    const process = (eye: any) => {
      const resized = webgazer.util.resizeEye(eye, resizeWidth, resizeHeight);
      if (!resized) return;
      const gray = webgazer.util.grayscale(
        resized.data,
        resized.width,
        resized.height
      );
      let hist: any = [];
      webgazer.util.equalizeHistogram(gray, 5, hist);
      return hist;
    };

    if (webgazer.params.trackEye == 'left') {
      return process(eyes.left);
    } else if (webgazer.params.trackEye == 'right') {
      return process(eyes.right);
    } else {
      return [].concat(process(eyes.left), process(eyes.right));
    }
  };
  webgazer.params = {
    ...webgazer.params,
    ...params,
  };
  return webgazer;
}

To make the intelisense work better I've also created a webgazer.d.ts and added to tsconfig.app.json imported types

declare module 'webgazer' {
  export interface GazeData {
    x: number;
    y: number;
  }
  export interface WebGazerParams {
    applyKalmanFilter: boolean;
    camConstraints: WebGazerParamsCamConstraints;
    dataTimestep: number;
    faceFeedbackBoxId: string;
    faceFeedbackBoxRatio: number;
    faceOverlayId: string;
    gazeDotId: string;
    getEventTypes: () => string[];
    mirrorVideo: boolean;
    moveTickSize: number;
    saveDataAcrossSessions: boolean;
    showFaceFeedbackBox: boolean;
    showFaceOverlay: boolean;
    showGazeDot: boolean;
    showVideo: boolean;
    showVideoPreview: boolean;
    storingPoints: number;
    trackEye: 'left' | 'right' | 'both';
    videoContainerId: string;
    videoElementCanvasId: string;
    videoElementId: string;
    videoViewerHeight: number;
    videoViewerWidth: number;
  }
  export interface WebGazerParamsCamConstraints {
    video: WebGazerParamsCamConstraintsVideo;
  }
  export interface WebGazerParamsCamConstraintsVideo {
    width: WebGazerParamsCamConstraintsVideoSize;
    height: WebGazerParamsCamConstraintsVideoSize;
  }
  export interface WebGazerParamsCamConstraintsVideoSize {
    min: number;
    ideal: number;
    max: number;
  }
  export interface WebGazerUtil extends any {
    getEyeFeats: (eye: any) => any;
    resizeEye: (
      eye: any,
      resizeWidth: number,
      resizeHeight: number
    ) => ImageData;
    grayscale: (data: Uint8ClampedArray, width: number, height: number) => any;
    equalizeHistogram: (src: any, step: any, dst: any) => any;
  }
  export interface WebGazer {
    webgazer: WebGazer;
    setGazeListener(
      callback: (data: GazeData | null, elapsedTime: number) => void
    ): WebGazer;
    begin(): Promise<WebGazer>;
    pause(): WebGazer;
    resume(): WebGazer;
    resetCalibration(): WebGazer;
    showPredictionPoints(show: boolean): WebGazer;
    showVideo(show: boolean): WebGazer;
    showFaceOverlay(show: boolean): WebGazer;
    isReady(): boolean;
    params: WebGazerParams;
    util: WebGazerUtil;
  }

  const webgazer: WebGazer;
  export default webgazer;
  export = webgazer;
}

And here is how I start it in my component page

  async startWebGazer() {
   // don't forget to import your composable
    const webgazer = await useWebgazer();
    await webgazer
      .setGazeListener((data, elapsedTime) => {
        if (!data) return;
        this.eyePosition = {
          x: data.x,
          y: data.y,
        };
      })
      .begin();
  }

This way at least everything that I need for now is working, and if I need to change anything else I can just create an override to the desired method and use the current imported webgazer instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants