vladmandic / face-api

FaceAPI: AI-powered Face Detection & Rotation Tracking, Face Description & Recognition, Age & Gender & Emotion Prediction for Browser and NodeJS using TensorFlow/JS
https://vladmandic.github.io/face-api/demo/webcam.html
MIT License
852 stars 153 forks source link

could i loadimages without canvas ? #91

Closed toguvr closed 2 years ago

toguvr commented 2 years ago

Issue Description Canvas is with problems to deploy and do u know what is the best way to do a similarity api without canvas ? i want compare an image (that i uploaded with multer, and an image from an url). thats my code:

`const faceDetectionNet = faceapi.nets.ssdMobilenetv1; const minConfidence = 0.5;

function getFaceDetectorOptions() {
  return new faceapi.SsdMobilenetv1Options({ minConfidence });
}

const faceDetectionOptions = getFaceDetectorOptions();

const user = await this.usersRepository.findById(user_id);

if (!user) {
  throw new AppError('Usuário não autenticado.');
}

if (!user?.avatar) {
  // Deletar avatar anterior se já tinha
  throw new AppError('Usuário sem foto.');
}

const response = await faceDetectionNet.loadFromUri(MODEL_URL);
console.log(response);
// await faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL);
// await faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL);
// await faceapi.nets.ssdMobilenetv1.loadFromUri(MODEL_URL);
const isFaceDetectionModelLoaded = !!faceapi.nets.ssdMobilenetv1.params;

if (!isFaceDetectionModelLoaded) {
  throw new AppError('Usuário não autenticado.');
}

const avatar_url = user.getAvatarUrl();
const originalPath = path.resolve(uploadConfig.tmpFolder, avatarFilename);

//here i need change. const referenceImage = await canvas.loadImage(originalPath); const queryImage = await canvas.loadImage(avatar_url);

const resultsRef = await faceapi.detectAllFaces(
  referenceImage,
  faceDetectionOptions,
);

const resultsQuery = await faceapi.detectAllFaces(
  queryImage,
  faceDetectionOptions,
);

const faceImages1 = await faceapi.extractFaces(referenceImage, resultsRef);
const faceImages2 = await faceapi.extractFaces(queryImage, resultsQuery);
let distance = 1;

if (faceImages1.length > 0 && faceImages2.length > 0) {
  const fim1 = await faceapi.computeFaceDescriptor(faceImages1[0]);
  const fim2 = await faceapi.computeFaceDescriptor(faceImages2[0]);

  distance = faceapi.utils.round(faceapi.euclideanDistance(fim1, fim2));
} else {
  throw new AppError('Rostos não encontrados na imagem.');
}
await fs.promises.unlink(originalPath);

return distance;`
vladmandic commented 2 years ago

package canvas is only really needed if you want to draw outputs on it in nodejs, otherwise there is a much simpler way

for example:

  await faceapi.nets.ssdMobilenetv1.loadFromDisk('model');
  await faceapi.nets.faceLandmark68Net.loadFromDisk('model');
  await faceapi.nets.faceRecognitionNet.loadFromDisk('model');
  await faceapi.nets.faceExpressionNet.loadFromDisk('model');
  const optionsSSDMobileNet = new faceapi.SsdMobilenetv1Options({ minConfidence: 0.1, maxResults: 10 });
  const buffer = fs.readFileSync('demo/sample1.jpg'); // read jpg image as binary data
  const decodeT = faceapi.tf.node.decodeImage(buffer, 3); // decode jpg buffer into rgb tensor
  const expandT = faceapi.tf.expandDims(decodeT, 0); // add batch dimension to rbg tensor
  const result = await faceapi.detectAllFaces(expandT, optionsSSDMobileNet)
    .withFaceLandmarks()
    .withFaceExpressions()
    .withFaceDescriptors();
  faceapi.tf.dispose([decodeT, expandT]); // dispose tensors
  console.log({ result });
toguvr commented 2 years ago

Nice! But we can't use readfileasync for url images like images in s3 buckets

vladmandic commented 2 years ago

it works just the same with fetch or any method that returns a full buffer (and there are methods like that for s3 buckets as well). for example:

    const res = await fetch(imageUrl);
    if (res && res.ok) buffer = await res.buffer();
toguvr commented 2 years ago

when i do this, return this to me: Cannot read properties of undefined (reading 'length')

vladmandic commented 2 years ago

copy & paste a full stack trace, not just last line. and where does this error occur exactly?

toguvr commented 2 years ago

I fixed!thanks for your help, the problem was fim1 is an array and nos an object, sorry my mistake, thanks for the help.

vladmandic commented 2 years ago

you're welcome!