LoginSignup
0
0

ChatGPTを使ってP5.jsとMediapipeでサクッと指認識した話

Posted at

ChatGPTの1周年とP5.js+Mediapipeを使用した手の指認識

ChatGPTの1周年について

2022年の11月30日にChatGPTがリリースされて1年が経過しました。この1年であらゆる環境にAIが活躍するようになり、世界が大きく変わった1年だったように思います。勿論このものすごいスピードでの変化は今も続いていますが、個人的にもChatGPTをはじめとするAIツールはいくつも試していますが、やはり1番利用しているのはChatGPTです。月3000円の有料課金は正直高いですが(2000円なら言う事なし!)、毎日使えば3000円以上の価値は十分にあると思います。逆に言うと月3000円を高いと思って使っていない人の方が断然多い訳で、そんな人たちと差を作るのなら今しかないとも思っています。様々な分野で活躍しますし、GPT-4はめちゃくちゃ賢いですから。絶対契約して毎日使うと人生が変わる気がしています。

P5.jsとMediapipeでの手の指認識について

今回はP5.jsとMediapipeで手の指認識をした話をさせてください。ChatGPTを使えば理解がメチャクチャ早くなる事例を含めての話です。

P5.js+Mediapipeを使いたかった訳

画像認識や手の認識には以前から興味があり、今回指の認識をしたいと思いました。高性能画像認識はGoogleが開発したMediapipe!これ本当にすごいですよね。P5.jsの前にRaspberry Pi 4で動かしていたのですが、処理が遅くて実用的ではありませんでした。そこで調べていくとGoogleのサンプル等をブラウザで試すとめちゃ軽い!JavaScriptの方がパフォーマンスが良いとわかったので、試してみる事に!

以下を参考にしました。
参考記事

P5.jsとindex.htmlとsketch.jsを記述する事で描画できるようになります。index.htmlの内容は、p5.jsとMediaPipe Hands APIを使用して、ブラウザでリアルタイムに手の追跡を行うウェブアプリケーションの基盤を構築するためのHTMLドキュメントです。主要な構成要素は以下の通りです:

  • p5.jsライブラリの読み込み: クリエイティブコーディングに使われるJavaScriptライブラリで、描画やアニメーションのために利用されます。
  • MediaPipeライブラリの読み込み: カメラ操作、UIコントロール、描画機能、そして手の追跡機能を提供するための複数のJavaScriptスクリプトが含まれています。
  • スタイルシート: 外部のCSSファイルを参照し、ウェブページのスタイルを定義しています。
  • ビデオ要素: カメラの映像を表示し、MediaPipeでの手の追跡に利用されるHTML要素です。
  • JavaScriptスクリプト: p5.jsやMediaPipeを使った具体的な処理を記述するための外部スクリプトファイル(sketch.js)を読み込んでいます。

この構造により、ユーザーのブラウザ上でカメラを通じて手の動きを捉え、それをリアルタイムで画面上に描画するアプリケーションを実現しています。

sketch.jsによるMediaPipeの実装

const isFlipped = true;

let keypointsHand = [];

const videoElement = document.getElementsByClassName("input_video")[0];
videoElement.style.display = "none";

function onHandsResults(results) {
  keypointsHand = results.multiHandLandmarks;
}

const hands = new Hands({
  locateFile: (file) => {
    return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
  },
});

hands.setOptions({
  selfieMode: isFlipped,
  maxNumHands: 1,
  modelComplexity: 1,
  minDetectionConfidence: 0.5,
  minTrackingConfidence: 0.5,
});
hands.onResults(onHandsResults);

const camera = new Camera(videoElement, {
  onFrame: async () => {
    await hands.send({ image: videoElement });
  },
  width: 1280,
  height: 720,
});
camera.start();

let videoImage;

function setup() {
  const canvas = createCanvas(500, 400);
  videoImage = createGraphics(320, 180);
}

function draw() {
  clear();
  background("rgba(100, 100, 255, 0.2)");

  videoImage.drawingContext.drawImage(
    videoElement,
    0,
    0,
    videoImage.width,
    videoImage.height
  );

  push();
  if (isFlipped) {
    translate(width, 0);
    scale(-1, 1);
  }
  displayWidth = width;
  displayHeight = (width * videoImage.height) / videoImage.width;
  image(videoImage, 0, 0, displayWidth, displayHeight);
  pop();

  if (keypointsHand.length > 0) {
    const indexTip = keypointsHand[0][8];
    ellipse(indexTip.x * displayWidth, indexTip.y * displayHeight, 10);
  }
}

index.html

<!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>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0