<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kevin Tuazon</title>
    <description>The latest articles on DEV Community by Kevin Tuazon (@kvntzn).</description>
    <link>https://dev.to/kvntzn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F539130%2F33eca55e-bdac-49f4-9a62-fd7ab57e1a58.jpeg</url>
      <title>DEV Community: Kevin Tuazon</title>
      <link>https://dev.to/kvntzn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kvntzn"/>
    <language>en</language>
    <item>
      <title>Using Face-api in Nodejs</title>
      <dc:creator>Kevin Tuazon</dc:creator>
      <pubDate>Mon, 15 Mar 2021 06:32:44 +0000</pubDate>
      <link>https://dev.to/kvntzn/using-face-api-in-nodejs-38aj</link>
      <guid>https://dev.to/kvntzn/using-face-api-in-nodejs-38aj</guid>
      <description>&lt;p&gt;We will be using &lt;a href="https://github.com/vladmandic/face-api" rel="noopener noreferrer"&gt;vladmandic-face-api&lt;/a&gt; as it is compatible with tfjs 2.0.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up the project
&lt;/h1&gt;

&lt;p&gt;We wil be setting up the project and install some packages needed for this project. Initial setup that we need to use to setup the API to upload image, and navigate files/folders.&lt;br&gt;
&lt;code&gt;npm install express express-fileupload fs path&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;And this one is the face-api, tfjs that is also needed by the face api and canvas to draw the detected points.&lt;br&gt;
&lt;code&gt;npm install @vladmandic/face-api @tensorflow/tfjs canvas&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Setup express API and a file upload endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express");
const fileUpload = require("express-fileupload");

const app = express();
const port = process.env.PORT || 3000;

app.use(fileUpload());

app.post("/upload", async (req, res) =&amp;gt; {
  const { file } = req.files;

  console.log(file);
  res.send("Successfile upload");
});

app.listen(port, () =&amp;gt; {
  console.log("Server started on port" + port);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, I setup the key as &lt;strong&gt;file&lt;/strong&gt;.&lt;br&gt;
&lt;code&gt;const { file } = req.files;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We'll be using  postman for testing the API with form data body and &lt;strong&gt;file&lt;/strong&gt; as a key.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhq9g1l341x1miv02wstu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhq9g1l341x1miv02wstu.png" alt="image" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Adding FaceAPI
&lt;/h1&gt;

&lt;p&gt;Download the AI models &lt;a href="https://github.com/justadudewhohacks/face-api.js/tree/master/weights" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  You can play around on any models but for this example we will only use ssd mobile net for face detection.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs19a9xobw61affgmrmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs19a9xobw61affgmrmt.png" alt="image" width="370" height="86"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  faceapiService.js
&lt;/h2&gt;

&lt;p&gt;This file is where we use the face api, in &lt;strong&gt;main()&lt;/strong&gt; we  initialize the face api, tf  and locate the models. in &lt;strong&gt;image()&lt;/strong&gt; is where we pass the image data we upload and decode it to a tensorflow object and we pass that object to &lt;strong&gt;detect()&lt;/strong&gt; wherein it will return the result for the image that we uploaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const path = require("path");

const tf = require("@tensorflow/tfjs-node");

const faceapi = require("@vladmandic/face-api/dist/face-api.node.js");
const modelPathRoot = "./models";

let optionsSSDMobileNet;

async function image(file) {
  const decoded = tf.node.decodeImage(file);
  const casted = decoded.toFloat();
  const result = casted.expandDims(0);
  decoded.dispose();
  casted.dispose();
  return result;
}

async function detect(tensor) {
  const result = await faceapi.detectAllFaces(tensor, optionsSSDMobileNet);
  return result;
}

async function main(file) {
  console.log("FaceAPI single-process test");

  await faceapi.tf.setBackend("tensorflow");
  await faceapi.tf.enableProdMode();
  await faceapi.tf.ENV.set("DEBUG", false);
  await faceapi.tf.ready();

  console.log(
    `Version: TensorFlow/JS ${faceapi.tf?.version_core} FaceAPI ${
      faceapi.version.faceapi
    } Backend: ${faceapi.tf?.getBackend()}`
  );

  console.log("Loading FaceAPI models");
  const modelPath = path.join(__dirname, modelPathRoot);
  await faceapi.nets.ssdMobilenetv1.loadFromDisk(modelPath);
  optionsSSDMobileNet = new faceapi.SsdMobilenetv1Options({
    minConfidence: 0.5,
  });

  const tensor = await image(file);
  const result = await detect(tensor);
  console.log("Detected faces:", result.length);

  tensor.dispose();

  return result;
}

module.exports = {
  detect: main,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Updating the upload endpoint
&lt;/h1&gt;

&lt;p&gt;We'll be updating the endpoint and test if it is working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post("/upload", async (req, res) =&amp;gt; {
  const { file } = req.files;

  const result = await faceApiService.detect(file.data);

  res.json({
    detectedFaces: result.length,
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzipe35zuv8667ztrmy2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzipe35zuv8667ztrmy2h.png" alt="image" width="800" height="363"&gt;&lt;/a&gt;&lt;br&gt;
There you go, we  got it working and detect the faces.&lt;/p&gt;

&lt;p&gt;You can use any photos with people, I used this one for this example.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.istockphoto.com%2Fphotos%2Fgroup-portrait-of-a-creative-business-team-standing-outdoors-three-picture-id1146473249%3Fk%3D6%26m%3D1146473249%26s%3D612x612%26w%3D0%26h%3DW1xeAt6XW3evkprjdS4mKWWtmCVjYJnmp-LHvQstitU%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.istockphoto.com%2Fphotos%2Fgroup-portrait-of-a-creative-business-team-standing-outdoors-three-picture-id1146473249%3Fk%3D6%26m%3D1146473249%26s%3D612x612%26w%3D0%26h%3DW1xeAt6XW3evkprjdS4mKWWtmCVjYJnmp-LHvQstitU%3D" alt="image" width="612" height="408"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Draw Detections
&lt;/h1&gt;

&lt;p&gt;Now we'll be adding the detected result and draw those into the image to see if it really detects the correct faces.&lt;/p&gt;
&lt;h2&gt;
  
  
  saveFile.js
&lt;/h2&gt;

&lt;p&gt;We'll create a new utils folder with this file to add a utility to save the detected images. We are also adding a out folder where we keep the detected images&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require("fs");
const path = require("path");

const baseDir = path.resolve(__dirname, "../out");

function saveFile(fileName, buf) {
  if (!fs.existsSync(baseDir)) {
    fs.mkdirSync(baseDir);
  }

  fs.writeFileSync(path.resolve(baseDir, fileName), buf);
}

module.exports = {
  saveFile,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqnp3jd9wmtpfhwf1105w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqnp3jd9wmtpfhwf1105w.png" alt="image" width="426" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating faceapiService.js
&lt;/h1&gt;

&lt;p&gt;We  are adding this code to draw the detections&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const canvas = require("canvas");
const { Canvas, Image, ImageData } = canvas;
faceapi.env.monkeyPatch({ Canvas, Image, ImageData });

async function main(file, filename){

 //...Existing code

  const result = await detect(tensor);
  console.log("Detected faces:", result.length);

  const canvasImg = await canvas.loadImage(file);
  const out = await faceapi.createCanvasFromMedia(canvasImg);
  faceapi.draw.drawDetections(out, result);
  save.saveFile(filename, out.toBuffer("image/jpeg"));
  console.log(`done, saved results to ${filename}`);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Updating upload endpoint
&lt;/h1&gt;

&lt;p&gt;Now we are almost finish, we are going to expose the saved image and add a url to the upload response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post("/upload", async (req, res) =&amp;gt; {
  const { file } = req.files;

  const result = await faceApiService.detect(file.data, file.name);

  res.json({
    detectedFaces: result.length,
    url: `http://localhost:3000/out/${file.name}`,
  });
});

app.use("/out", express.static("out"));

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll try the postman again.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qwc16j62sneixfhepsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qwc16j62sneixfhepsm.png" alt="image" width="800" height="375"&gt;&lt;/a&gt;&lt;br&gt;
There you go we got the detected faces, able to draw and expose the image.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k5aloly08j9qicil5ez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k5aloly08j9qicil5ez.png" alt="image" width="800" height="446"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I also created a github repository for reference. &lt;a href="https://github.com/kvntzn/face-api" rel="noopener noreferrer"&gt;face-api&lt;/a&gt;.  &lt;/p&gt;

</description>
      <category>node</category>
      <category>tensorflow</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Hello world</title>
      <dc:creator>Kevin Tuazon</dc:creator>
      <pubDate>Sat, 12 Dec 2020 20:10:38 +0000</pubDate>
      <link>https://dev.to/kvntzn/test-3154</link>
      <guid>https://dev.to/kvntzn/test-3154</guid>
      <description>&lt;p&gt;Hello world&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
