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

Error in toNetInput function - Expected media to be of type HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, or tf.Tensor3D #960

Open
SamLorenzoSanc opened this issue Feb 15, 2025 · 0 comments

Comments

@SamLorenzoSanc
Copy link

I'm encountering an error when attempting to use face-api.js in a Node.js environment with a node-canvas generated canvas. The error occurs when trying to pass a canvas to the toNetInput function. The error message is:

Error: toNetInput - expected media to be of type HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | tf.Tensor3D, or to be an element id at /path/to/node_modules/face-api.js/build/commonjs/dom/toNetInput.js:38:35 ...

I'm using node-canvas to load an image, resize it, and then create a canvas using createCanvas from the node-canvas package.
The canvas (localCanvas) is created and drawn onto, but when I try to pass it to face-api.js via the toNetInput function, it throws the above error.

`export const loginFacial = async (req, res) => {
try {
const { username } = req.body;

if (!req.file) {
  return res.status(400).json({ message: 'No file uploaded' });
}

const user = await User.findOne({ username });
if (!user) {
  return res.status(404).json({ message: 'User not found' });
}

if (!user.faceId || user.faceId.length === 0) {
  return res.status(400).json({ message: 'No face ID stored for user' });
}

await loadFaceApiModels();

const img = await loadImage(req.file.path);

const MAX_WIDTH = 640;
const MAX_HEIGHT = 480;
const scale = Math.min(MAX_WIDTH / img.width, MAX_HEIGHT / img.height);
const newWidth = img.width * scale;
const newHeight = img.height * scale;

const localCanvas = createCanvas(newWidth, newHeight);
const ctx = localCanvas.getContext('2d');
ctx.drawImage(img, 0, 0, newWidth, newHeight);

const input = await faceapi.toNetInput(localCanvas);
console.log('Input para face-api.js:', input); // Check the input being passed

const detections = await faceapi.detectSingleFace(input, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceDescriptor();
if (!detections) {
  return res.status(401).json({ message: 'No face detected' });
}

const storedFaceDescriptor = new Float32Array(user.faceId);
const faceMatcher = new faceapi.FaceMatcher([storedFaceDescriptor]);
const bestMatch = faceMatcher.findBestMatch(detections.descriptor);

if (bestMatch.distance < 0.6) {
  const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
  return res.json({ token });
} else {
  return res.status(401).json({ message: 'Face authentication failed' });
}

} catch (error) {
console.error('Error in loginFacial:', error);
res.status(500).json({ message: 'Internal Server Error' });
}
};
`

I am passing the localCanvas (created by node-canvas) directly to face-api.js via faceapi.toNetInput(localCanvas). Even though localCanvas is a valid canvas object from node-canvas, the error suggests that face-api.js does not accept it as valid input. The toNetInput function seems to expect a standard HTMLCanvasElement, HTMLImageElement, or HTMLVideoElement from the browser context, but this is not a browser environment.

face-api.js should accept a node-canvas canvas object when running in a Node.js environment, as it can handle it properly for face detection.

face-api.js version: 0.22.2
node-canvas version: 3.1.0
Node.js version: 18.20.4

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

No branches or pull requests

1 participant