개요

 


 

1. 모델 설명 | Used to

모델 설명
  • 모델명: MediaPipe Attention Mesh
  • 구체적인 설명
A lightweight model for real-time prediction of 3D facial surface landmarks from video captured by a front-facing smartphone camera.
Designed for applications like AR makeup, eye tracking and AR puppeteering that rely on highly accurate landmarks for eye (+ iris) and lips regions predicted by the model. Runs at over 50 FPS on Pixel 2 phone.

 

Used to
  • 특정 신원에 대한 얼굴 또는 얼굴 특징에 대해서는 저장할 수 없음에 주의
Applications
 - Detection of human facial surface landmarks from monocular video.
 - Optimized for videos captured on front-facing cameras of smartphones.
 - Well suitable for mobile AR (augmented reality) applications.

Domain & Users
 - The primary intended application is AR entertainment.
 - Intended users are people who use augmented reality for entertainment purposes.

Out-of-scope applications
Not appropriate for:
 - This model is not intended for human life-critical decisions.
 - Predicted face landmarks do not provide facial recognition or identification and do not store any unique face representation.

 


 

2. Model type 및 Model architecture

모델 카드 인용
MobileNetV2 - like with customized blocks for real-time performance and an attention mechanism to refine lips and eye regions and to predict irises.

 

Model type: CNN

 

Model architecture
  • face-landmarks-detection 에서는 detector-model과 landmark-model이라고 하지 않고, 각각을 sub model이라고 칭함
  • 입, 눈, 눈동자를 제외한 박스 안에 있는 얼굴 부위 탐지 및 좌표 예측: MobileNetV2
  • 입, 눈, 눈동자의 탐지 및 좌표 예측: attention mechanism
    • 특히 이 메커니즘에서 spatial transformer 모듈이 사용됨
    • 이 모듈은 아핀 변환 행렬(affine transformation matrix)에 의해 조절되고, 사용자가 박스 안의 keypoint를 당기고 회전하고 바꾸고 왜곡할 수 있게 함
attention mechanism
An attention mechanism pulls out visual features of a given region of interest by sampling a grid of 2D points in the feature space and extracting the features under the sampled points. This allows to train architectures end-to-end and to enrich the features that are used by the attention mechanism.

spatial transformer
Specifically, we use a spatial transformer module which is controlled by an affine transformation matrix and allows us to zoom, rotate, translate, and skew the sampled grid of points.

 


 

3. input, output

Inputs
Image of cropped face with 25% margin on each side and size 192x192 px.

Output(s)
 - Facial surface represented as 468 3D landmarks flatened into a 1D tensor: (x1, y1, z1), (x2, y2, z2), ... x- and y-coordinates follow the image pixel coordinates;
z-coordinates are relative to the face center of mass and are scaled proportionally to the face width.
 - Lips refined region surface represented as 80 2D landmarks (inner and outer contours and an intermediate line) flattened into a 1D tensor.
 - Eye with eyebrow refined region surface (x2) represented as 71 2D landmarks (eye and eyebrow contours with surrounding areas) flattened into a 1D tensor.
 - Iris refined region surface (x2) represented as 5 2D landmarks (1 for pupil center and 4 for iris contour) flattened into a 1D tensor.
 - Face flag indicating the likelihood of the face being present in the input image. Used in tracking mode to detect that the face was lost and the face detector should be applied to obtain a new face position. Face probability threshold is set at 0.5 by default and can be adjusted.
[
  {
    box: {
      xMin: 304.6476503248806,
      xMax: 502.5079975897382,
      yMin: 102.16298762367356,
      yMax: 349.035215984403,
      width: 197.86034726485758,
      height: 246.87222836072945
    },
    keypoints: [
      {x: 406.53152857172876, y: 256.8054528661723, z: 10.2, name: "lips"},
      {x: 406.544237446397, y: 230.06933367750395, z: 8},
      ...
    ],
  }
]

 


 

4. evaluation metric

face의 metric : IOD MAE
  • 양쪽 눈 사이의 거리의 평균 오차
  • IOD (Normalization by Interocular Distance)
Normalization by interocular distance (IOD) is applied to unify the scale of the samples.
IOD is calculated as the distance between the eye centers (which are estimated as the centers of segments connecting eye corners) and is taken as 100%.
To accommodate head rotations, 3D IOD from the ground truth is employed.
  • MAE (Mean Absolute Error normalized by interocular distance) : handpose와 동일
Mean absolute error is calculated as the pixel distance between ground truth and predicted face mesh.
The model provides 3D coordinates, but as the z screen coordinates as well as metric world coordinates are obtained from synthetic data, so for a fair comparison with human annotations, only 2D screen coordinates MNAE are employed.

 

evaluation results
  • 구체적인 내용
Comparison with fairness goal of 2.56% IOD MAE discrepancy across 17 regions:
 - Tracking mode: from 2.73% to 3.95% (difference of 1.22%)
 - Reacquisition mode: from 3.01% to 4.28% (difference of 1.27%)

Comparison with our fairness criteria yields a maximum discrepancy between best and worst performing regions of 1.22% for the tracking mode and 1.27% for the reacquisition mode.
We therefore consider the models performing well across groups.
  • Tracking mode and Reacquisition mode
  Tracking mode Reacquisition mode
발동 상황 메인 모드
 = 대부분의 얼굴 감지 가능한 일반적인 상황
 = 이전 프레임에서 높은 정확도의 얼굴 정보를 얻을 수 있을 때
이전 프레임에서 얼굴 정보를 얻을 수 없을 때
 = 첫 번째 프레임 or 얼굴 추적 정보가 없어졌을 때
이용하는 툴 the Mdiapipe Python Solution API for face mesh BlazeFace Detector
Tracking mode
The main mode that takes place most of the time and is based on obtaining a highly accurate face crop from the prediction on the previous frame (frames 2, 3, ... on the image below). Underneath we utilize the MediaPipe Python Solution API for Face Mesh and run the pipeline for several frames on the same image before measuring the tracking accuracy (thus the crop region is determined from the model predictions as in a video stream).

Reacquisition mode
Takes place when there is no information about the face from previous frames. It happens either on the first frame (image below) or on the frames where the face tracking is lost. In this case, an external face detector is being run over the whole frame. We used BlazeFace Detector for the evaluation of the reacquisition mode.

 

문제 인식

  • 정지 버튼을 누르면 캔버스에 그려졌던 손, 얼굴, 포즈의 keypoints와 path가 남아있는 현상
  • 사수께서 clearRect() 함수가 정상적으로 적용되지 않았다고 알려주심

 


 

cleatRect() 함수 사용법

const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(20, 20, 200, 100);
ctx.clearRect(40, 40, 50, 50);
  • 결과물 : 빨간색 context 내부에 설정한 크기의 사각형의 색이 지워졌음

  • 그러나 이 코드가 개별 detector 함수에 들어가면 안 됨 (∵ 향후 다른 detector 함수와 함께 실행하였을 때 오류 가능성)
  • 따라서 detector 관련 코드를 모두 관리하는 detector-manager 코드에서 clearRect() 함수를 적용해야 함

 


 

해결법

  • draw 하여 캔버스에 비디오를 그리기 전에 clearRect 하여 이전의 캔버스를 지워야함
  • 지속적으로 렌더링되어 캔버스에 이미지가 그려지기 때문
if (result) {
  if (dt.drawBox) {
      dt.context.clearRect(0,0,Detector.DIMENSIONS[0],Detector.DIMENSIONS[1]);
      dt.detector.draw(dt.canvas);
      this._renderer.updateBitmapSkin(dt.skinId, dt.canvas, 1);
  } 
} else {
  if (dt.drawBox && hasResult) {
      dt.context.clearRect(0,0,Detector.DIMENSIONS[0],Detector.DIMENSIONS[1]);
      this._renderer.updateBitmapSkin(dt.skinId,dt.canvas,1);
  }
}

문제 인식

  • 일렉트론으로 구현해보았을 때는 이하 코드처럼 라이브 비디오 자체를 매개변수로 예측하였음.
const hands = await detector.estimateHands(camera.video, { flipHorizontal: false });
  • 그러나 자사 소프트웨어 기존 코드에서는 estimate 함수의 매개변수가 이미지임. 따라서 기존 방식을 따라 가야 했음

 


 

1. Tensorflow.js 공식 깃헙

  • 매개변수의 확인 → 이미지와 비디오 둘 다 가능!
  • 따라서 이미지로 estimate 함수 사용하여 일렉트론으로 구현해보고자 함
// 이미지
const result = await detector.estimateHands(image, {
  staticImageMode: true
} as handPoseDetection.MediaPipeHandsTfjsEstimationConfig);

// 비디오
const hands = await detector.estimateHands(video, null /* config */);

 


 

2. 일렉트론으로 구현 

  • 핵심 로직
    1. ctx.drawImage(video, 0, 0, canvas.width, canvas.height) 
      : 웹 캠에서 받아온 비디오 현재 프레임을 캔버스에 표시
    2. ctx.getImageData(0, 0, canvas.width, canvas.height)
      : 캔버스의 이미지 데이터를 가져옴 (캡처)
  • 핵심 코드 
_captureImageData(video) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = video.videoWidth;  
  canvas.height = video.videoHeight;
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);  
  return ctx.getImageData(0, 0, canvas.width, canvas.height);
}

// estimate 함수에 적용
const detector = createDetector(SupportedModels.MediapipeHands);
const imageData = HandposeDetector.captureImageData(video);
const result = await detector.estimateHands(imageData);

 


 

해결법 (요약)

  • GUI 프로젝트 코드에 이미 video → image 로 바꾸는 로직이 작성되어 있었음
// drawImage()
if (lastUpdate + cacheTimeout < now) {
  try {
      if (mirror) {
          context.scale(-1, 1);
          context.translate(width * -1, 0);
      }
      context.drawImage(this._element,
          // source x, y, width, height
          0, 0, elementDimension.width, elementDimension.height,
          // dest x, y, width, height
          0, 0, width, height
      );
      context.setTransform(1, 0, 0, 1, 0, 0);
      workspace.lastUpdate = now;
  } catch {
      return null;
  }
}

// getImageData()
if (formatCache.lastUpdate + cacheTimeout < now) {
	if (format === CameraProvider.FORMAT_IMAGE_DATA) {
	    formatCache.lastData = context.getImageData(0, 0, width, height);
}

 

  • 나는 이미 정해져 있는 detect 함수의 매개변수인 imageData를 가져와 처리함
detect(imageData) {
	return new Promise((resolve, reject) => {   
    this._detector.estimateHands(imageData).then(result => {
        this._result = result;
        console.log(`this._result: `, this._result);

        this._result.forEach((res) => {
            console.log(`${res.handedness} hand keypoints:`);
            res.keypoints.forEach((keypoint, i) => {
                let x = keypoint.x - 320;
                let y = keypoint.y - 240;
                console.log(`Keypoint ${i}: [${x}, ${y}]`);
            })
        })
        resolve(this._result);
    }).catch(e => {
        reject(e);
    });
	})
}

 

 

 

개요

 


 

1. npm install 해야 할 최소한의 모듈

<!-- 둘이 set-->
npm install @tensorflow-models/hand-pose-detection --legacy-peer-deps
npm install @mediapipe/hands --legacy-peer-deps

<!-- 위의 핵심 라이브러리를 실행할 수 있도록 하기 위한 peer dependency-->
npm install @tensorflow/tfjs --legacy-peer-deps
npm install @tensorflow/tfjs-converter --legacy-peer-deps
npm install @tensorflow/tfjs-core --legacy-peer-deps
  • 추가적으로 필요하다고 여겨지는 @tensorflow/tfjs-backend-webgl @tensorflow/tfjs-backend-wasm @tensorflow/tfjs-backend-webgpu 은 이하 peer dependency 에 이미 포함되어 있음
  • 특히 webgl을 tf.setBackend(’webgl’) 식으로 설정할 필요도 없음. 아래 설치하고 핵심 라이브러리를 require 하면 자동 설정됨
  • 주의할 점 : peer dependency 충돌 해결하는 글 보러 가기

이하 글의 코드와 글의 근본적인 출처는 Tensorflow-models 공식 깃헙입니다!

 

개요

  • 이하에서는 이번 프로젝트에서 구현한 hand-pose-detection, face-landmarks-detection, pose-detection 모델을 로딩하는 방법을 정리하였음.
  • 위 모델들을 로딩한다는 것 = createDetector() 함수를 실행한다는 것 
  • 이하 방법은 model loading 시리즈 2편인 npm install 해야하는 최소한의 모듈 글을 참고해서 코드를 짜야 보다 효율적임
  • 또한 createDetector() 함수를 오프라인으로 저장한 모델과 함께 사용하는 경우, 버전을 제대로 맞추지 않는다면 quantization 오류를 계에에에에속 맞닥뜨릴 것임. 따라서 해당 오류를 해결한 글과 함께 보길 권장함 

 


 

1. CDN

  • CDN 이란 
    • Contents Delivery Network : 콘텐츠 전송 네트워크
    • 콘텐츠를 임시 저장 서버에 옮겼다가 수요가 있을 때 콘텐츠를 전달
  • 핵심 코드 : 이하 코드는 Tensorflow-models 공식 깃헙에서 demo 코드로 명시한 방법
<!-- Require the peer dependencies of hand-pose-detection. -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter"></script>

<!-- You must explicitly require a TF.js backend if you're not using the TF.js union bundle. -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgl"></script>

<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/hand-pose-detection"></script>

 


 

2. npm install + require( 또는 import )

  • npm 모듈 설치 
npm install @tensorflow-models/hand-pose-detection
npm install @tensorflow/tfjs-core, @tensorflow/tfjs-converter
npm install @tensorflow/tfjs-backend-webgl
  • require (또는 import)
// require
const {createDetector,SupportedModels} = require("@tensorflow-models/hand-pose-detection");

// import
import * as handPoseDetection from '@tensorflow-models/hand-pose-detection';
import * as tf from '@tensorflow/tfjs-core';
// Register WebGL backend.
import '@tensorflow/tfjs-backend-webgl';
  • 그러나 위의 1번, 2번 방법은 온라인 환경에서만 정상 작동한다는 단점이 있음. 이를 보완하는 방법으로 모델을 오프라인으로 저장해서 불러오는 3번이 있음

 


 

3. 오프라인 저장 

  • 모델을 오프라인 저장 해야 하는 이유
    1. CORS 에러 (Cross-Origin Resource Sharing)
      • 웹 브라우저가 다른 도메인, 프로토콜, 포트에서 실행되는 웹페이지에서 리소스를 요청할 때 발생
      • 따라서 모델을 오프라인 저장하지 않고, localhost:5050 에서 localhost:8888 로 model.json을 요청한다면,
        웹 브라우저가 포트 번호가 달라 다른 출처(origin)으로 간주하고 CORS 정책에 따라 요청 차단함
      • CORS에 대해 보다 전문적으로 설명한 글 보러 가기 
 

CORS

 

ko.javascript.info

       2. 자사 소프트웨어 특성 상 인터넷이 끊어져도 제품 사용할 수 있어야 함
          : 그러나 CDN 방식과 npm install 방식은 온라인 상태여야만 Tensorflow-models의 npm 모듈 사용 가능

 

 

Find Pre-trained Models | Kaggle

Use and download pre-trained models for your machine learning projects.

www.kaggle.com

       

        2. createDetector() 함수의 옵션 지정 : detectorModelUrl, landmarkModelUrl 모델 저장 장소 지정

_createDetector() {
  const model = SupportedModels.MediaPipeHands;
  const detector = createDetector(model, {
      runtime: "tfjs",
      modelType: "lite",
      maxHands: 2, // or 2~10.
      flipHorizontal: false,
      staticImageMode: false,
      detectorModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_detector_lite_1/model.json",
      landmarkModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_landmark_lite_1/model.json",
  });
  return detector;
}

 

      3. 비동기로 모델 로딩

if (!this._detector) {
    this._createDetector().then(detector => {
        this._detector = detector;
        console.log("model loading success!, detector: ", this._detector);
    })
}

 

      4. 모델 로딩 결과 : <pending> → 펼치면 “fulfilled” 출력되어야 함

개요

Tensorflow-models에 속해 있는 모델들의 전형적인 사용 구조를 설명하려고 함. 미래의 나를 위해... 이하 모든 글과 코드는 근본적으로 Tensorflow-models 공식 깃헙에 출처가 있음.

 


 

1. model loading : createDetector

_createDetector() {
  const model = SupportedModels.MediaPipeHands;
  const detector = createDetector(model, {
      runtime: "tfjs",
      modelType: "lite",
      maxHands: 2, // or 2~10.
      flipHorizontal: false,
      staticImageMode: false,
      detectorModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_detector_lite_1/model.json",
      landmarkModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_landmark_lite_1/model.json",
  });

  console.log("model loading success!, detector: ", this._detector);
  return detector;
}

 


 

2. detect

  • detector.estimateHands(video or image)
  • estimateFaces 등 다양한 시리즈 있음
detect(imageData) {
  if (!this._detector) {
      this._createDetector().then(detector => {
          this._detector = detector;
          console.log("model loading success!, detector: ", this._detector);
      })
  }

  return new Promise((resolve, reject) => {   
      this._detector.estimateHands(imageData).then(result => {
          this._result = result;
          console.log(`this._result: `, this._result);

          this._result.forEach((res) => {
              console.log(`${res.handedness} hand keypoints:`);
              res.keypoints.forEach((keypoint, i) => {
                  let x = keypoint.x - 320;
                  let y = keypoint.y - 240;
                  console.log(`Keypoint ${i}: [${x}, ${y}]`);
              })
          })
          resolve(this._result);
      }).catch(e => {
          reject(e);
      });
  })
}

 


 

3. draw : draw(canvas) 등 매개 변수는 다양할 수 있음

  • drawKeypoint
  • drawPath
draw(canvas) {
    if (!canvas || !this.isExistContent(this._result)) return canvas;
    const ctx = canvas.getContext("2d");
    if (this._result) {
        this._result.forEach( (res) => {
            ctx.fillStyle = res.handedness === "Left" ? "Red" : "Blue";
            ctx.strokeStyle = "White";
            ctx.lineWidth = 2;
            res.keypoints.forEach(keypoint => {
                this._drawKeypoint(ctx, keypoint);
            });
            Object.keys(FINGER_INDICES).forEach(finger => {
                const points = FINGER_INDICES[finger].map(idx => res.keypoints[idx]);
                this._drawPath(ctx, points, false);
            });
        });
    }
    return canvas;
}

_drawKeypoint(ctx, keypoint) {
    ctx.beginPath();
    ctx.arc(keypoint.x - 2, keypoint.y - 2, 3, 0, 2 * Math.PI);
    ctx.fill();
}

_drawPath(ctx, points, closePath) {
    const region = new Path2D();
    region.moveTo(points[0].x, points[0].y);
    points.slice(1).forEach(point => region.lineTo(point.x, point.y));
    if (closePath) {
        region.closePath();
    }
    ctx.stroke(region);
}

 

 

이하 글은 Tensorflow-models 모델 로딩을 위해 공부하고 문제를 해결한 글입니다.

모델 버전 관리 - 1. model-loading 글 보러 가기 

2023.11.30 - [AI/TensorFlow | Tensorflow.js] - [Tensorflow-models] 모델 버전 관리 - 1. model loading

 


 

문제 인식

  • npm install 
    • npm install @tensorflow/tfjs npm install @tensorflow/tfjs-converter npm install @tensorflow/tfjs-core npm install @tensorflow-models/hand-pose-detection 등을 실행하여 npm 모듈을 설치할 때, peer dependency 충돌이 있으면 다음과 같은 오류가 발생함.
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! 
npm ERR! While resolving: @tensorflow-models/mobilenet@2.0.4
npm ERR! Found: @tensorflow/tfjs-converter@4.10.0
npm ERR! node_modules/@tensorflow/tfjs-converter
npm ERR!   peer @tensorflow/tfjs-converter@"^4.9.0" from @tensorflow-models/hand-pose-detection@2.0.1
npm ERR!   node_modules/@tensorflow-models/hand-pose-detection
npm ERR!     @tensorflow-models/hand-pose-detection@"^2.0.1" from the root project
npm ERR!   @tensorflow/tfjs-converter@"4.10.0" from @tensorflow/tfjs@4.10.0
npm ERR!   node_modules/@tensorflow/tfjs
npm ERR!     @tensorflow/tfjs@"^4.10.0" from the root project
npm ERR!   2 more (the root project, @tensorflow-models/face-detection)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @tensorflow/tfjs-converter@"~1.2.1" from @tensorflow-models/mobilenet@2.0.4
npm ERR! node_modules/@tensorflow-models/mobilenet
npm ERR!   @tensorflow-models/mobilenet@"2.0.4" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: @tensorflow/tfjs-converter@1.2.11
npm ERR! node_modules/@tensorflow/tfjs-converter
npm ERR!   peer @tensorflow/tfjs-converter@"~1.2.1" from @tensorflow-models/mobilenet@2.0.4
npm ERR!   node_modules/@tensorflow-models/mobilenet
npm ERR!     @tensorflow-models/mobilenet@"2.0.4" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

 

  • npm 모듈 사용(실행)
    • 특정 모델을 로딩하여 예측 시도할 때 (코드 실행할 때), peer dependency 충돌이 있으면 다음과 같은 오류가 발생하기도 함
    • 그러나 오류 양상이 다양하므로 밑 종류 하나 만으로 한정할 수 없음
    • 따라서 ‘~찾을 수 없음’, ‘resolve 하다가 ~없어서 문제 발생함’ 등의 뉘앙스의 오류는 peer dependency로 인한 오류가 아닐까? 의심해야 함
client:159 ./node_modules/scratch-vm/node_modules/@tensorflow/tfjs-converter/dist/tf-converter.esm.js
Module build failed: Error: ENOENT: no such file or directory, open 'C:\Workspace\Rogic\scratch-gui\node_modules\scratch-vm\node_modules@tensorflow\tfjs-converter\dist\tf-converter.esm.js'

 

  • 주의할 점은 npm install 할 때를 제외하고, peer dependency로 인한 오류임에도 콘솔에서 직접적으로 알려주지 않는다는 것
    • 따라서 두번째 느낌으로 발생한 오류는 궁극적으로 peer dependency로 발생하는 오류일 수 있음을 인지해야 함
    • 여타 오류 해결 방법을 사용하기 전, 후에 peer dependency로 인한 오류가 아닐까? 의심해야 함

 


 

충돌 원인 : 실제 설치된 패키지 버전 ≠ peer dependency에서 요구하는 패키지 버전

  • peer dependency 의미
    • 친구 패키지 명 + 버전
    • 친구 패키지 : 해당 패키지를 정상적으로 활용하기 위해 필요한 다른 패키지
    • 즉 실제로 패키지에서 직접 require(import) 하지는 않더라도 호환성이 필요한 경우 명시하는 것
    • npm 3 버전까지는 peer dependency를 자동으로 설치해줌, 4 - 6 버전에서는 경고 메시지만 띄워줌, 7 버전부터는 peer dependency 버전이 맞지 않으면 설치 불가
      → 나의 npm - -version : 9.6.4 , 그렇다면 실제 설치된 버전 ≠ peer dependency 요구 버전이라면 해당 패키지 아예 설치 및 실행 불가? NO!
      → 해결법은 맨 마지막에!

 

  • peer dependency 확인
    • package-lock.json
"node_modules/@tensorflow-models/hand-pose-detection": {
    "version": "2.0.1",
    "resolved": "https://registry.npmjs.org/@tensorflow-models/hand-pose-detection/-/hand-pose-detection-2.0.1.tgz",
    "integrity": "sha512-zRA+jz2qOq5FMcyqSFxaQyi6T4YNbMbQhd6SQMI791FQ8yYj23kLgYa73g2NssR5AmM/2ATu9Vcjnf7LUrVLOQ==",
    "dependencies": {
        "rimraf": "^3.0.2",
        "tslib": "^2.6.1"
    },
    "peerDependencies": {
        "@mediapipe/hands": "~0.4.0",
        "@tensorflow/tfjs-backend-webgl": "^4.9.0",
        "@tensorflow/tfjs-converter": "^4.9.0",
        "@tensorflow/tfjs-core": "^4.9.0"
    }
  },
  • dependency vs dev dependency
    1. dependency
      • 앱에 종속된 가장 일반적인 종속성
      • 런타임빌드타임개발중 일 때 모두 필요
      • 따라서 앱이 빌드될 때 여기에 속해 있는 패키지들이 모두 번들에 포함되어 배포
    2. dev dependency
      • 빌드타임개발중 일 때 필요
      • 따라서 앱이 빌드될 때 도움 주거나 참조 되지만, 번들에 포함X

 


 

해결법 (요약)

  • npm 7 버전부터는 peer dependency 버전이 맞지 않으면 설치 불가
    • 그러나 무조건 peer dependency에서 얘기하는 딱! 그! 버전만 설치해야 패키지 실행할 수 있다는 것은 말이 안 됨 (사용자마다 프로젝트, pc 상황이 다를 수 있기 때문)
    • 해결 방법은 npm 공식 깃헙 블로그 기준 2가지가 있음 : --force 또는 --legacy-peer-deps
    • 더보기
      You have the option to retry with --force to bypass the conflict or --legacy-peer-deps command to ignore peer dependencies entirely (this behavior is similar to versions 4-6). - in npm github blog
  • 2가지 방법 요약
    --force --legacy-peer-deps
    충돌 우회 충돌 무시
    package-lock.json에 몇 가지의 다른 의존 버전들을 추가 peerDependency가 맞지 않아도 일단 설치
    • 이번 프로젝트에서는 주로 --legacy-peer-deps 를 활용하여 peer dependency 충돌 해결 (사수 제안)
    • 그러나 일반적인 경우 --force--legacy-peer-deps 로 적용해보는 것이 좋을 것 같음
      ( ∵ --force--legacy-peer-deps 보다 덜 강제적)

 


 

이번 프로젝트 (Tensorflow-models 구현) 에서 주의할 점

  • peer dependency를 설치한 경우, 해당 패키지가 실제 실행 가능한지 빌드 + 실행해서 확인 필수
    • 실행해보아야 하는 것 : ①모델 로딩(create detector) ②예측(estimateHands)
  • 해당 프로젝트의 경우 다음과 같은 버전 특징을 갖고 있었음
      hand-pose-detection face-landmarks-detection pose-detection
    peer dependency 권장 버전 "peerDependencies":
    { "@mediapipe/hands": "~0.4.0", "@tensorflow/tfjs-backend-webgl": "^4.9.0", "@tensorflow/tfjs-converter": "^4.9.0", "@tensorflow/tfjs-core": "^4.9.0" }
    "peerDependencies":
    { "@mediapipe/face_detection": "~0.4.0", "@tensorflow/tfjs-backend-webgl": "^4.4.0", "@tensorflow/tfjs-converter": "^4.4.0", "@tensorflow/tfjs-core": "^4.4.0" }
    "peerDependencies":
    { "@mediapipe/pose": "~0.5.0", "@tensorflow/tfjs-backend-wasm": "^4.10.0", "@tensorflow/tfjs-backend-webgl": "^4.10.0", "@tensorflow/tfjs-backend-webgpu": "^4.10.0", "@tensorflow/tfjs-converter": "^4.10.0", "@tensorflow/tfjs-core": "^4.10.0" }
    실제 실행 가능한 최소 버전 ( hand-pose-detection, face-landmarks-detection, pose-detection 최신 버전 기준) - tfjs, tfjs-core, tfjs-converter : ^3.3.0 - tfjs, tfjs-core, tfjs-converter : ^3.3.0 - tfjs, tfjs-core, tfjs-converter : ^4.4.0
    • 위처럼 ①모델마다 실제 실행 가능한 최소 버전 및 권장 peer dependency 버전이 상이하고 ②향후 프로젝트 확장 가능성 고려하여 , 사수님 제안으로 tfjs, tfjs-core, tfjs-converter 모델 모두 4.10.0 으로 설치함
    • tfjs, tfjs-core, tfjs-converter 모델은 2점대 이후로 버전이 한 몸으로 움직임. 따라서 버전업 할 때도 한 번에 했음
    • 위 3개 모델을 제외한 나머지 모델 ( ex. @tensorflow/tfjs-backend-webgl @tensorflow/tfjs-backend-wasm @tensorflow/tfjs-backend-webgpu) 은 위 3개 모델을 설치하면 자동 실행되므로 별도 설치 필요 없음
      ( 사실 @tensorflow/tfjs-converter 도 4점대 이후에는 포함되어있지만 그 전에는 포함되어 있지 않으므로, 보수적으로 별도 설치함)

 

+ Recent posts