javascriptvue.jsmediapipe

mediapipe javascript to vue component?


I'm building a project that need's to use mediapipe and I don't know how to implement it into my Vue.js project. Can you guys help me? I would love to install the mediapie model through npm, and import it at vue component.

This is the code:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/control_utils/control_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js" crossorigin="anonymous"></script>
</head>

<body>
  <div class="container">
    <video class="input_video"></video>
    <canvas class="output_canvas" width="1280px" height="720px"></canvas>
  </div>
</body>
</html>

<script type="module">
  const videoElement = document.getElementsByClassName('input_video')[0];
  const canvasElement = document.getElementsByClassName('output_canvas')[0];
  const canvasCtx = canvasElement.getContext('2d');
  
  function onResults(results) {
    canvasCtx.save();
    canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
    canvasCtx.drawImage(
        results.image, 0, 0, canvasElement.width, canvasElement.height);
    if (results.multiHandLandmarks) {
      for (const landmarks of results.multiHandLandmarks) {
        drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS,
                       {color: '#00FF00', lineWidth: 5});
        drawLandmarks(canvasCtx, landmarks, {color: '#FF0000', lineWidth: 2});
      }
    }
    canvasCtx.restore();
  }
  
  const hands = new Hands({locateFile: (file) => {
    return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
  }});
  hands.setOptions({
    maxNumHands: 1,
    minDetectionConfidence: 0.6,
    minTrackingConfidence: 0.5
  });
  hands.onResults(onResults);
  
  const camera = new Camera(videoElement, {
    onFrame: async () => {
      await hands.send({image: videoElement});
    },
    width: 1280,
    height: 720
  });
  camera.start();
  </script>

Solution

  • I have figured it out, this is the code for people who facing problem using mediapipe in Vue.js

    <template>
      <div class="container">
        <video ref="input_video" width="100%" height="100%"></video>
        <canvas
          class="output_canvas"
          ref="output_canvas"
          :width="width"
          :height="height"
        ></canvas>
      </div>
    </template>
    <script>
    import { Hands, HAND_CONNECTIONS } from "@mediapipe/hands";
    import { Camera } from "@mediapipe/camera_utils";
    import { drawConnectors, drawLandmarks } from "@mediapipe/drawing_utils";
    
    export default {
      name: "HandModel",
      data: function() {
        return {
          number: null,
          ctx: null,
          width: null,
          height: null,
        };
      },
      computed: {
        inputVideo() {
          return this.$refs.input_video;
        },
      },
      mounted() {
        this.ctx = this.$refs.output_canvas.getContext("2d");
        this.init();
      },
      methods: {
        init() {
          const hands = new Hands({
            locateFile: (file) => {
              return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
            },
          });
          hands.setOptions({
            maxNumHands: 1,
            minDetectionConfidence: 0.5,
            minTrackingConfidence: 0.5,
          });
          hands.onResults(this.onResults);
    
          const camera = new Camera(this.inputVideo, {
            onFrame: async () => {
              await hands.send({ image: this.inputVideo });
            },
          });
          camera.start();
        },
        onResults(results) {
          this.width = results.image.width;
          this.height = results.image.height;
          this.ctx.save();
          this.ctx.clearRect(0, 0, results.image.width, results.image.height);
          this.ctx.drawImage(
            results.image,
            0,
            0,
            results.image.width,
            results.image.height
          );
          this.findHands(results);
          this.ctx.restore();
        },
        findHands(results, draw = true) {
          if (results.multiHandLandmarks) {
            for (const landmarks of results.multiHandLandmarks) {
              drawConnectors(this.ctx, landmarks, HAND_CONNECTIONS, {
                color: "#00FF00",
                lineWidth: 5,
              });
              if (draw) {
                drawLandmarks(this.ctx, landmarks, {
                  color: "#FF0000",
                  lineWidth: 2,
                });
              }
            }
          }
        },
      },
    };
    </script>
    
    <style scoped>
    .output_canvas {
      width: 100%;
      height: 100%;
    }
    </style>