顔の表情を認識し、顔のAPIを使用して絵文字に顔を変更します.次はJS.タイプスクリプト


おい、人々.
私はアプリケーションを開発したface-api.js , それは顔の表情を認識し、顔をリアルタイムに顔を変更!

本稿では、このアプリケーションの開発方法を説明します.
デモ→ https://face2emoji.vercel.app/
ギタブ→ https://github.com/yuikoito/face2emoji

私が開発した理由


最近、もっとたくさんのオンラインミーティングをしてきたし、顔を見せたくない時もある.
個人的には自分の顔を見せたくないのですが、もちろん表情をよく理解しています.
それから、自分の表情だけを見せることができれば、それは素晴らしいことかと思っていました.lol
あなたは、実際のWeb会議として、このアプリケーションを使用することはできませんが、十分な要求があれば、私はそれが実際のWeb会議に使用できるようにクロム拡張機能を作る.
さあ、どうやって自分の考えを教えてくれたか試してみてください.

アプリケーション構造と機能


次は使用します.アプリケーションを作成するJS +タイプスクリプト.
顔の認識は顔APIを使用して行われます.TensorFlowに基づくモジュールJSjs
そして、ホスティングはvercelです.
機能は簡単です:アプリが起動されると、顔と顔の表情を認識し、あなたの顔に絵文字を置きます.
絵文字はアップル絵文字です.
顔APIで.JS、表情の7つのパターンを得ることができます、そして、それぞれのために、各々の式のために以下のEmojisがセットされます.


を、今はどのようにこのアプリケーションを開発する方法を説明する時間です.

フェイスAPIのセットアップとインストール。js


$ yarn create next-app <app-name>
$ cd <app-name>
$ touch tsconfig.json
$ yarn add --dev typescript @types/react
次に、インデックス名を変更します.JSとRainアプリ.インデックスへのJS.TSX、Rainアプリ.TSX
ウェブカメラをインストールします.
$ yarn add react-webcam @types/react-webcam
これでフェイスAPIをインストールする準備ができました.js
$ yarn add face-api.js
ReadMe、面APIで述べられるように.JSはモデルをロードする必要があります.
それで、重みフォルダをコピーしてくださいface-api.js github そして、人前でそれを置いてください.
名前からモデルへの名前変更
モデルを読み込みます.
ここでは、TinyFaceDetectorとFaceExpressionNetを使用しています.
SSDmobilenetv 1では、精度はより良いでしょうが、それは非常に重いので、いくつかのデバイスが動作しません.
  const loadModels = async () => {
    const MODEL_URL = "/models";
    await Promise.all([
      faceapi.nets.tinyFaceDetector.load(MODEL_URL),
      faceapi.nets.faceExpressionNet.load(MODEL_URL),
    ]);
  };
ログが正しく出力されているか確認しましょう.
ボタンをクリックして顔を認識し、次のようにログを参照してください.
// pages/index.tsx

import * as faceapi from "face-api.js";
import { useRef } from "react";
import Webcam from "react-webcam";

export default function Home() {
  const webcamRef = useRef<Webcam>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const loadModels = async () => {
    const MODEL_URL = "/models";
    await Promise.all([
      faceapi.nets.tinyFaceDetector.load(MODEL_URL),
      faceapi.nets.faceExpressionNet.load(MODEL_URL),
    ]);
  };

  const faceDetectHandler = async () => {
    await loadModels();
    if (webcamRef.current && canvasRef.current) {
      const webcam = webcamRef.current.video as HTMLVideoElement;
      const canvas = canvasRef.current;
      webcam.width = webcam.videoWidth;
      webcam.height = webcam.videoHeight;
      canvas.width = webcam.videoWidth;
      canvas.height = webcam.videoHeight;
      const video = webcamRef.current.video;
      const detectionsWithExpressions = await faceapi
        .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())
        .withFaceExpressions();
      console.log(detectionsWithExpressions);
    }
  };

  return (
    <div className={styles.container}>
      <main className={styles.main}>
        <Webcam audio={false} ref={webcamRef} className={styles.video} />
        <canvas ref={canvasRef} className={styles.video} />
        <button onClick={faceDetectHandler}>顔認識</button>
      </main>
    </div>
  );
}

いいですね.
検出部は顔認識部であり、座標等を含む.
今私たちがしなければならないすべての顔の場所をチェックし、最高のスコアを式に基づいて絵文字を描画します.

表情による絵文字の変更


描画部分は長いので、ロジックを別のファイルに入れます.
からの検出とキャンバスを送るべきですindex.tsx .
式オブジェクトを計算しやすいフォームに変更します.
// expressions output
{
  angry: 0.00012402892753016204
  disgusted: 0.00000494607138534775
  fearful: 2.4963259193100384e-7
  happy: 0.00011926032311748713
  neutral: 0.9996343851089478
  sad: 0.00010264792217640206
  surprised: 0.000014418363207369111
}
次のように変更します.
    const Array = Object.entries(detectionsWithExpression.expressions);
    const scoresArray = Array.map((i) => i[1]);
    const expressionsArray = Array.map((i) => i[0]);
全体のコードは次の通りです.
// utils/drawEmoji.ts

import {
  WithFaceExpressions,
  FaceDetection,
  FaceExpressions,
} from "face-api.js";

export const drawEmoji = async (
  detectionsWithExpressions: WithFaceExpressions<{
    detection: FaceDetection;
    expressions: FaceExpressions;
  }>[],
  canvas: HTMLCanvasElement
) => {
  detectionsWithExpressions.map((detectionsWithExpression) => {
    const ctx = canvas.getContext("2d");
    const Array = Object.entries(detectionsWithExpression.expressions);
    const scoresArray = Array.map((i) => i[1]);
    const expressionsArray = Array.map((i) => i[0]);
    const max = Math.max.apply(null, scoresArray);
    const index = scoresArray.findIndex((score) => score === max);
    const expression = expressionsArray[index];
    const image = document.createElement("img");
    image.onload = () => {
      const width = detectionsWithExpression.detection.box.height * 1.2;
      const height = detectionsWithExpression.detection.box.height * 1.2;
      const x = detectionsWithExpression.detection.box.x - width * 0.1;
      const y = detectionsWithExpression.detection.box.y - height * 0.2;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(image, x, y, width, height);
    };
    image.src = `/emojis/${expression}.png`;
  });
};
ところで、今回は複数の人が検出できますので、ctx.clearRect(0, 0, canvas.width, canvas.height); 上記の場所では、マップが順番に流れ、複数の人々がある場合は、一人が検出され、描画され、他は描画されません.
この理由により、複数の人をサポートしたい場合は、一時的なキャンバス要素を準備する必要があります.
ここでは、複数の人々が使用するためのものではありません.
とにかく、今、ロジック部分が行われ、あなたがしなければならないすべてはindex.tsx .

展開に関する注意:モジュールが見つかりません: ' fs 'サポートを解決できません


顔APIから.JSはノードでも利用できます.いくつかの使用FS.しかし、もちろんブラウザで実行するときにFSは必要ないので、この部分での展開時にエラーが発生します.
したがって、ブラウザで実行するときにFSが使用されないことを明示的に指定する必要があります.
この部分は次のような課題で報告された.
https://github.com/justadudewhohacks/face-api.js/issues/154
次に、次を変更します.設定.以下のように.
// next.config.js
module.exports = {
  reactStrictMode: true,
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        fs: false,
      };
    }
    return config;
  },
};

必要なら読むmy github .

それだ!


この記事は毎週少なくとも1つの記事を書きたいという12週目です.
あなたが望むならば、私の前の毎週のポストを見てください!
すぐにお会いしましょう!

連絡先


あなたが仕事を提供するか、私に何かを尋ねるならば、私にメッセージを送ってください.
  • [email protected]