vladmandic / human

Human: AI-powered 3D Face Detection & Rotation Tracking, Face Description & Recognition, Body Pose Tracking, 3D Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction, Gaze Tracking, Gesture Recognition
https://vladmandic.github.io/human/demo/index.html
MIT License
2.19k stars 313 forks source link

Error: Argument 'x' passed to 'squeeze' must be a Tensor or TensorLike, but got 'null' #478

Open zmk-punchbowl opened 2 weeks ago

zmk-punchbowl commented 2 weeks ago

Issue Description

We encountered this error Error: Argument 'x' passed to 'squeeze' must be a Tensor or TensorLike, but got 'null'. To be clear, we've been using version 3.2.1 for a while without ever seeing this issue. I'm unsure at this point what caused it.

Screenshot 2024-07-09 at 11 48 00 AM

Steps to Reproduce

I'm currently unsure. We're using human to detect faces in videos for a while, without this issue. It does not happen regularly. This is the first time I've seen it.

Expected Behavior

To not encounter this error (or at least to be able to catch it and proceed).

Environment

Diagnostics

Additional

zmk-punchbowl commented 2 weeks ago

Okay, after some follow-up investigation, I believe this error happened because we were in an unexpected state caused by a previous error (a process ran out of memory and encountered ENOMEM). That would explain why we never saw this before. For us, the bug is the original error (running out of memory). It's possible that this caused us to feed a corrupt/incomplete file into human. Could that cause the error above?

vladmandic commented 2 weeks ago

Definitely possible, need to take a look at the code around the stack trace you've posted.

zmk-punchbowl commented 2 weeks ago

Definitely possible, need to take a look at the code around the stack trace you've posted.

Our main usage looks like this:

export async function detectFacesInImage(
  imgFile: string
): Promise<FaceResult[]> {
  const buffer = fs.readFileSync(imgFile);
  const tensor = (await getHuman()).tf.node.decodeImage(buffer);
  const res = await (await getHuman()).detect(tensor);

  // Dispose all tensors
  if (res?.face) {
    res.face.forEach(async (f: FaceResult) =>
      (await getHuman()).tf.dispose(f.tensor)
    );
  }

  return res.face as FaceResult[];
}

Our only other call into the library is to assess similarity:

      const s = (await getHuman()).match.similarity(
        faceToFind.embedding!,
        face.embedding!
      );

It may be possible in this scenario that the file indicated by imgFile would be corrupt.