React + TypeScript: Tensorflow로 얼굴 감지

안녕 얘들아

실시간으로 얼굴에 자동으로 마스크를 적용하는 얼굴 감지 기능이 있는 애플리케이션을 개발했습니다.



이 기사에서는 이 애플리케이션을 개발하는 방법에 대해 설명합니다.

데모→ https://mask-app-one.vercel.app/
github→ https://github.com/YuikoIto/mask-app

이 응용 프로그램에는 로딩 애니메이션이 없으므로 처음 로딩할 때 몇 초 동안 기다려야 합니다.

react 애플리케이션 설정 및 react-webcam 설치



$ npx create-react-app face-mask-app --template typescript
$ yarn add react-webcam @types/react-webcam

그런 다음 웹 카메라를 설정해 보십시오.

// App.tsx

import { useRef } from "react";
import "./App.css";
import Webcam from "react-webcam";

const App = () => {
  const webcam = useRef<Webcam>(null);

  return (
    <div className="App">
      <header className="header">
        <div className="title">face mask App</div>
      </header>
      <Webcam
        audio={false}
        ref={webcam}
        style={{
          position: "absolute",
          margin: "auto",
          textAlign: "center",
          top: 100,
          left: 0,
          right: 0,
        }}
      />
    </div>
  );
}

export default App;

yarn start 및 액세스http://localhost:3000/ .



예이! 이제 웹 카메라를 사용할 수 있습니다.

Tensorflow를 사용하여 얼굴 감지를 사용해 보세요.



여기에서는 이 모델을 사용하고 있습니다. https://github.com/tensorflow/tfjs-models/tree/master/face-landmarks-detection

$ yarn add @tensorflow-models/face-landmarks-detection @tensorflow/tfjs-core @tensorflow/tfjs-converter @tensorflow/tfjs-backend-webgl


  • TypeScript를 사용하지 않는 경우 모두 설치할 필요가 없습니다. @tensorflow/tfjs , @tensorflow/tfjs-core@tensorflow/tfjs-converter 대신 @tensorflow/tfjs-backend-webgl 를 설치하십시오.

  • // App.tsx
    
    import "@tensorflow/tfjs-core";
    import "@tensorflow/tfjs-converter";
    import "@tensorflow/tfjs-backend-webgl";
    import * as faceLandmarksDetection from "@tensorflow-models/face-landmarks-detection";
    import { MediaPipeFaceMesh } from "@tensorflow-models/face-landmarks-detection/dist/types";
    
    const App = () => {
      const webcam = useRef<Webcam>(null);
    
      const runFaceDetect = async () => {
        const model = await faceLandmarksDetection.load(
          faceLandmarksDetection.SupportedPackages.mediapipeFacemesh
        );
        detect(model);
      };
    
      const detect = async (model: MediaPipeFaceMesh) => {
        if (webcam.current) {
          const webcamCurrent = webcam.current as any;
          // go next step only when the video is completely uploaded.
          if (webcamCurrent.video.readyState === 4) {
            const video = webcamCurrent.video;
            const predictions = await model.estimateFaces({
              input: video,
            });
            if (predictions.length) {
              console.log(predictions);
            }
          }
        };
      };
    
      useEffect(() => {
        runFaceDetect();
      // eslint-disable-next-line react-hooks/exhaustive-deps
      }, [webcam.current?.video?.readyState])
    
    


    로그를 확인하십시오.



    좋아, 좋아 보인다.

    얼굴에 마스크를 오버레이하도록 캔버스 설정


    <canvas> 아래에 <Webcam>를 추가합니다.

    //App.tsx
    const App = () => {
      const webcam = useRef<Webcam>(null);
      const canvas = useRef<HTMLCanvasElement>(null);
    
      return (
        <div className="App">
          <header className="header">
            <div className="title">face mask App</div>
          </header>
          <Webcam
            audio={false}
            ref={webcam}
          />
          <canvas
            ref={canvas}
          />
    
    


    영상과 캔버스의 크기를 맞춥니다.

        const videoWidth = webcamCurrent.video.videoWidth;
        const videoHeight = webcamCurrent.video.videoHeight;
        canvas.current.width = videoWidth;
        canvas.current.height = videoHeight;
    


    그럼 this map을 보고 어디를 채워야 하는지 확인해보자.

    이 지도로 보면 195번이 코 주변이다. 그래서 이 지점을 받침점으로 설정합니다. beginPath()〜closePath() 를 이용하여 쉽게 마스크를 그려봅시다.

    // mask.ts
    
    import { AnnotatedPrediction } from "@tensorflow-models/face-landmarks-detection/dist/mediapipe-facemesh";
    import {
      Coord2D,
      Coords3D,
    } from "@tensorflow-models/face-landmarks-detection/dist/mediapipe-facemesh/util";
    
    const drawMask = (
      ctx: CanvasRenderingContext2D,
      keypoints: Coords3D,
      distance: number
    ) => {
      const points = [
        93,
        132,
        58,
        172,
        136,
        150,
        149,
        176,
        148,
        152,
        377,
        400,
        378,
        379,
        365,
        397,
        288,
        361,
        323,
      ];
    
      ctx.moveTo(keypoints[195][0], keypoints[195][1]);
      for (let i = 0; i < points.length; i++) {
        if (i < points.length / 2) {
          ctx.lineTo(
            keypoints[points[i]][0] - distance,
            keypoints[points[i]][1] + distance
          );
        } else {
          ctx.lineTo(
            keypoints[points[i]][0] + distance,
            keypoints[points[i]][1] + distance
          );
        }
      }
    };
    
    export const draw = (
      predictions: AnnotatedPrediction[],
      ctx: CanvasRenderingContext2D,
      width: number,
      height: number
    ) => {
      if (predictions.length > 0) {
        predictions.forEach((prediction: AnnotatedPrediction) => {
          const keypoints = prediction.scaledMesh;
          const boundingBox = prediction.boundingBox;
          const bottomRight = boundingBox.bottomRight as Coord2D;
          const topLeft = boundingBox.topLeft as Coord2D;
          // make the drawing mask larger a bit
          const distance =
            Math.sqrt(
              Math.pow(bottomRight[0] - topLeft[0], 2) +
                Math.pow(topLeft[1] - topLeft[1], 2)
            ) * 0.02;
          ctx.clearRect(0, 0, width, height);
          ctx.fillStyle = "black";
          ctx.save();
          ctx.beginPath();
          drawMask(ctx, keypoints as Coords3D, distance);
          ctx.closePath();
          ctx.fill();
          ctx.restore();
        });
      }
    };
    
    


    App.tsx에서 이draw 함수를 가져와서 사용하세요.

    
        const ctx = canvas.current.getContext("2d") as CanvasRenderingContext2D;
        requestAnimationFrame(() => {
          draw(predictions, ctx, videoWidth, videoHeight);
        });
    


    마치다!

    읽어 주셔서 감사합니다.
    Tensorflow를 처음 사용하지만 공식 github 저장소의 좋은 README 덕분에 작은 응용 프로그램을 쉽게 만들 수 있습니다. Tensorflow를 사용하여 더 발전하겠습니다 🐣

    🍎🍎🍎🍎🍎🍎

    필요하시면 쪽지 주세요.
  • [email protected]


  • 🍎🍎🍎🍎🍎🍎

    참조


  • Canvasでよく使う描画テクまとめ
  • tfjs-models
  • Iris landmark tracking in the browser with MediaPipe and TensorFlow.js
  • 좋은 웹페이지 즐겨찾기