More Related Content
PPTX
OpenVRやOpenXRの基本的なことを調べてみた PDF
【Unity道場 2月】シェーダを書けるプログラマになろう PDF
はじめようARCore:自己位置推定・平面検出・FaceTracking PDF
PDF
シェーダだけで世界を創る!three.jsによるレイマーチング PDF
xR Developerなら知っておきたいカメラの基礎知識 PPTX
PDF
Open3DでSLAM入門 PyCon Kyushu 2018 What's hot
PDF
【Unity】 Behavior TreeでAIを作る PDF
PDF
PDF
PDF
【Unity】より良い表現のためのライティング戦略 PDF
PDF
PPTX
PDF
【Unity道場】VectorGraphicsで作る エモい表現 PDF
OpenCV/ARCore/Unityで作る塗り絵AR PDF
PDF
「のどが渇いた」というユーザーに何を出す? ユーザーの「欲しい」に惑わされない、本当のインサイトを見つけるUXデザイン・UXリサーチ PDF
CEDEC2017 アーティストのためのリアルタイムシェーダー学習法 PDF
PDF
Cartographer を用いた 3D SLAM PDF
【Unity道場スペシャル 2017大阪】トゥーンシェーダー・マニアクス2 〜ユニティちゃんトゥーンシェーダー2.0徹底解説〜 PDF
PPTX
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発 ODP
PDF
Similar to AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう
PPTX
A-Frameで始めるWebXRとハンドトラッキング (HoloLens2/Oculus Quest対応) PPTX
OpenCVでつくろうARスタンプアプリ in 熊本 PDF
PPTX
HoloLens2とMeta QuestではじめるWebXR PPTX
AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう PPTX
AI x WebAR MediaPipeの顔認識を使ってみよう! in 織りなすラボ PDF
A-Frameで始めるOculus Quest対応WebVR PDF
OpenCVとARCoreで作るスタンプAR in 宮崎 PPTX
AI x WebAR! MediaPipeの顔認識を使ってみよう! PDF
PDF
手と物体とのInteractionを検出するアプリケーションの開発 PDF
PDF
WebXR Hand Input (ハンド トラッキング) 入門 PDF
Switch VisionⓇ Lite / Module 操作マニュアル More from Takashi Yoshinaga
PPTX
PPTX
PPTX
AI x WebXR: フェイストラッキングを用いた擬似3D表現を解説! PPTX
【準備編】OculusQuest/HoloLens2対応WebXR開発 PPTX
MRTKで始めるAR開発 (HoloLens 1 and 2, ARCore, ARkit) PPTX
【準備編!】HoloLens 2/Oculus Quest対応WebXRハンズオン PPTX
Voxon Photonics VX1で遊んでみた PPTX
Oculus Quest 1&2 開発のはじめの一歩 with A-Frame WebVR PPTX
iPad LiDARでエンジニアカフェを3Dスキャン PPTX
Holo-SDKハンズオン:はじめようヘッドトラッキングを用いた3D表現 PPTX
PPTX
ARコンテンツ作成勉強会( #AR_Fukuoka )紹介 PPTX
PPTX
Spatial Copy & Paste @HoloLensゆるっとLT会 PPTX
iPad LiDARで作ってみた in AR Fukuoka 忘年会2020 PPTX
PPTX
FUKUOKA Engineers Day 2021 発表資料:AR Fukuoka & HoloBox紹介 PPTX
エンジニアカフェ1周年イベント:WebAR/VR開発入門 PPTX
PPTX
OSC2020 Fukuoka: インストールいらず、WebAR入門 Recently uploaded
PDF
PCCC25(設立25年記念PCクラスタシンポジウム):コアマイクロシステムズ株式会社 テーマ 「AI HPC時代のトータルソリューションプロバイダ」 PDF
PCCC25(設立25年記念PCクラスタシンポジウム):Pacific Teck Japan テーマ3「『TrinityX』 AI時代のクラスターマネジメ... PDF
PCCC25(設立25年記念PCクラスタシンポジウム):Pacific Teck Japan テーマ2「『Slinky』 SlurmとクラウドのKuber... PDF
論文紹介:DiffusionRet: Generative Text-Video Retrieval with Diffusion Model PDF
論文紹介:HiLoRA: Adaptive Hierarchical LoRA Routing for Training-Free Domain Gene... PDF
論文紹介:MotionMatcher: Cinematic Motion Customizationof Text-to-Video Diffusion ... PDF
PCCC25(設立25年記念PCクラスタシンポジウム):日本ヒューレット・パッカード合同会社 テーマ1「大規模AIの能力を最大限に活用するHPE Comp... PDF
PCCC25(設立25年記念PCクラスタシンポジウム):エヌビディア合同会社 テーマ1「NVIDIA 最新発表製品等のご案内」 PDF
PCCC25(設立25年記念PCクラスタシンポジウム):日本ヒューレット・パッカード合同会社 テーマ3「IT運用とデータサイエンティストを強力に支援するH... PDF
PCCC25(設立25年記念PCクラスタシンポジウム):富士通株式会社 テーマ1「HPC&AI: Accelerating material develo... PPTX
ChatGPTのコネクタ開発から学ぶ、外部サービスをつなぐMCPサーバーの仕組み PPTX
2025年11月24日情報ネットワーク法学会大井哲也発表「API利用のシステム情報」 PDF
AI開発の最前線を変えるニューラルネットワークプロセッサと、未来社会における応用可能性 PDF
膨大なデータ時代を制する鍵、セグメンテーションAIが切り拓く解析精度と効率の革新 PDF
ニューラルプロセッサによるAI処理の高速化と、未知の可能性を切り拓く未来の人工知能 AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
ライブラリ読み込みの解説
<!--media pipe: 手の骨格取得や認識結果の描画に使用-->
<scriptsrc="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/
camera_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>
<!--opencv.js: 手の傾きや中心位置を計算するために使用-->
<script src="https://docs.opencv.org/3.4.1/opencv.js"></script>
OpenCV
Camera Utils Hands + drawing utils
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
初期化に関する記述
window.onload = function(){
let videoElement = document.getElementById('input_video');
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net /npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
maxNumHands: 2, //認識可能な手の最大数
modelComplexity: 1,//精度に関する設定(0~1)
minDetectionConfidence: 0.5,//手検出の信頼度
minTrackingConfidence: 0.5,//手追跡の信頼度
useCpuInference: false, //M1 MacのSafariの場合は1
});
//結果を処理する関数を登録
hands.onResults(recvResults);
//カメラの初期化
const camera = new Camera(videoElement, {
onFrame: async () => {
await hands.send({image: videoElement});
},
width: 1280, height: 720
});
camera.start(); //カメラの動作開始
};
function recvResults(results) {/*手の検出結果を利用する*/ }
- 27.
HTMLの要素との関連付け
window.onload = function(){
let videoElement = document.getElementById('input_video'); //ビデオ要素の取得
canvasElement = document.getElementById('output_canvas'); //表示用のCanvasを取得
canvasCtx = canvasElement.getContext('2d'); //Canvas描画に関する情報にアクセス
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
maxNumHands: 2, //認識可能な手の最大数
modelComplexity: 1,//精度に関する設定(0~1)
minDetectionConfidence: 0.5,//手検出の信頼度
minTrackingConfidence: 0.5,//手追跡の信頼度
useCpuInference: false, //M1 MacのSafariの場合は1
});
//結果を処理する関数を登録
hands.onResults(recvResults);
//カメラの初期化
const camera = new Camera(videoElement, {
onFrame: async () => {
await hands.send({image: videoElement});
},
width: 1280, height: 720
});
camera.start();
};
function recvResults(results) {/*手の検出結果を利用する*/ }
- 28.
ハンドトラッキングの初期化
window.onload = function(){
let videoElement = document.getElementById('input_video'); //ビデオ要素の取得
canvasElement = document.getElementById('output_canvas'); //表示用のCanvasを取得
canvasCtx = canvasElement.getContext('2d'); //Canvas描画に関する情報にアクセス
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net /npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
maxNumHands: 2, //認識可能な手の最大数
modelComplexity: 1,//精度に関する設定(0~1)
minDetectionConfidence: 0.5,//手検出の信頼度
minTrackingConfidence: 0.5,//手追跡の信頼度
useCpuInference: false, //M1 MacのSafariの場合はtrue
});
//結果を処理する関数を登録
hands.onResults(recvResults);
//カメラの初期化
const camera = new Camera(videoElement, {
onFrame: async () => {
await hands.send({image: videoElement});
},
width: 1280, height: 720
});
camera.start(); //カメラの動作開始
};
function recvResults(results) {/*手の検出結果を利用する*/ }
詳細は後ほど実装
- 29.
カメラの初期化と起動
window.onload = function(){
let videoElement = document.getElementById('input_video');
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net /npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
maxNumHands: 2, //認識可能な手の最大数
modelComplexity: 1,//精度に関する設定(0~1)
minDetectionConfidence: 0.5,//手検出の信頼度
minTrackingConfidence: 0.5,//手追跡の信頼度
useCpuInference: false, //M1 MacのSafariの場合は1
});
//結果を処理する関数を登録
hands.onResults(recvResults);
//カメラの初期化
const camera = new Camera(videoElement, {
onFrame: async () => {
await hands.send({image: videoElement});
},
width: 1280, height: 720
});
camera.start(); //カメラの動作開始
};
function recvResults(results) {/*手の検出結果を利用する*/ }
videoElementの映像を
ハンドトラッキング処理に渡す
画像サイズを設定
- 30.
- 31.
- 32.
- 33.
カメラ画像の表示
//手の検出結果を利用する
function recvResults(results) {
letwidth=results.image.width;
let height=results.image.height;
//画像のサイズとcanvasのサイズが異なる場合はサイズを調整
if(width!=canvasElement.width){
//入力画像と同じサイズのcanvas(描画領域)を用意
canvasElement.width=width;
canvasElement.height=height;
}
//以下、canvasへの描画に関する記述
canvasCtx.save();
//画像を表示
canvasCtx.drawImage(results.image, 0, 0, width, height);
canvasCtx.restore();
} Lesson02
(0,0)
width
height
- 34.
- 35.
- 36.
- 37.
- 38.
ハンドトラッキング結果の表示
Lesson03
canvasCtx.save();
//画像を表示
canvasCtx.drawImage(results.image, 0, 0,width, height);
//手を検出したならばtrue
if (results.multiHandLandmarks) {
//見つけた手の数だけ処理を繰り返す
for (const landmarks of results.multiHandLandmarks) {
//骨格を描画
drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS,
{color: '#00FF00', lineWidth: 2});
//関節を描画
drawLandmarks(canvasCtx, landmarks, {
color: '#FF0000', lineWidth: 1,radius:2});
}
}
canvasCtx.restore();
- 39.
- 40.
- 41.
- 42.
画像の反転
window.onload = function(){
let videoElement = document.getElementById('input_video');
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
selfieMode:true, //画像を左右反転
maxNumHands: 2, //認識可能な手の最大数
modelComplexity: 1,//精度に関する設定(0~1)
minDetectionConfidence: 0.5,//手検出の信頼度
minTrackingConfidence: 0.5,//手追跡の信頼度
useCpuInference: false, //M1 MacのSafariの場合は1
});
/*以下省略*/ Lesson04
- 43.
認識する手の数の上限を変更
window.onload = function(){
let videoElement = document.getElementById('input_video');
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
selfieMode:true, //画像を左右反転
maxNumHands: 1, //認識可能な手の最大数
modelComplexity: 1,//精度に関する設定(0~1)
minDetectionConfidence: 0.5,//手検出の信頼度
minTrackingConfidence: 0.5,//手追跡の信頼度
useCpuInference: false, //M1 MacのSafariの場合は1
});
/*以下省略*/ Lesson05
maxNumHandsを1に変更
- 44.
- 45.
- 46.
- 47.
- 48.
画像をスクリプトで扱う準備
let canvasElement;
let canvasCtx;
letbeam; //ライトセイバー的な画像
//初期化
window.onload = function() {
//画像の読み込み
beam = document.getElementById("beam");
let videoElement = document.getElementById('input_video’);
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({
/*省略*/
});
Lesson06
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
手の位置・角度の計算
let canvasElement;
let canvasCtx;
letbeam; //ライトセイバー的な画像
let ell; //手の位置や傾きを表す楕円
//初期化
window.onload = function() {
//画像の読み込み
beam = loadImage('画像のURL');
let videoElement = document.getElementById('input_video’);
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
//手の認識に関するオプション
hands.setOptions({ /*省略*/ });
Lesson10
- 65.
手の位置・角度の計算
function recvResults(results) {
/*描画領域のサイズ設定など(スペースの都合上省略)*/
if(results.multiHandLandmarks) {
//見つけた手の数だけ処理を繰り返す
for (const landmarks of results.multiHandLandmarks) {
drawConnectors(/*略*/);
drawLandmarks(canvasCtx, landmarks, {/*略*/);
cvFunction(landmarks,width,height);
drawLightSaber();
}
}
canvasCtx.restore();
}
//手の中心や傾きを計算
function cvFunction(landmarks,width,height){
}
Lesson11
- 66.
- 67.
- 68.
楕円の表示
function drawLightSaber(){
//楕円の角度
let angle= ell.angle;
//位置指定
canvasCtx.translate(ell.center.x, ell.center.y);
//角度指定
canvasCtx.rotate(angle * Math.PI /180.0);
//楕円を描画
canvasCtx.beginPath();
canvasCtx.ellipse(0, 0, //位置
ell.size.width/2.0, ell.size.height/2.0, //半径
0, 0, 2 * Math.PI); //角度と表示の開始・終了
canvasCtx.stroke();
//一旦コメント化
//canvasCtx.drawImage(beam, 0, 0, beam.width, beam.height);
}
Lesson13
- 69.
- 70.
- 71.
- 72.
画像を表示
Lesson14
function drawLightSaber(){
//楕円の角度
let angle= ell.angle;
//位置指定
canvasCtx.translate(ell.center.x, ell.center.y);
//角度指定
canvasCtx.rotate(angle * Math.PI /180.0);
//楕円を描画
canvasCtx.beginPath();
canvasCtx.ellipse(0, 0, //位置
ell.size.width/2.0, ell.size.height/2.0, //半径
0, 0, 2 * Math.PI); //角度と表示の開始・終了
canvasCtx.stroke();
//再度有効化
canvasCtx.drawImage(beam, 0, 0, beam.width, beam.height);
}
- 73.
- 74.
- 75.
角度の補正
Lesson15
function drawLightSaber(){
//楕円の角度
let angle= ell.angle;
//ライトセイバーの向きを反転
if(angle<90){ angle=angle-180; }
//位置指定
canvasCtx.translate(ell.center.x, ell.center.y);
//角度指定
canvasCtx.rotate(angle * Math.PI /180.0);
//楕円を描画
canvasCtx.beginPath();
canvasCtx.ellipse(0, 0, ell.size.width/2.0, ell.size.height/2.0,
0, 0, 2 * Math.PI);
canvasCtx.stroke();
canvasCtx.drawImage(beam, 0, 0, beam.width, beam.height);
}
- 76.
- 77.
サイズを大きくしよう
Lesson16
//楕円の角度
let angle =ell.angle;
//ライトセイバーの向きを反転
if(angle<90){ angle=angle-180; }
//デフォルトサイズを元画像の2倍くらいにしたい。
let mul = (ell.size.width*2.0)/beam.width;
//位置指定
canvasCtx.translate(ell.center.x, ell.center.y);
//角度指定
canvasCtx.rotate(angle * Math.PI /180.0);
//楕円を描画
canvasCtx.beginPath();
canvasCtx.ellipse(0, 0, ell.size.width/2.0, ell.size.height/2.0,
0, 0, 2 * Math.PI);
canvasCtx.stroke();
//デフォルトサイズに倍数をかける
canvasCtx.scale(mul, mul);
canvasCtx.drawImage(beam, 0, 0, beam.width, beam.height);
- 78.
- 79.
- 80.
画像の位置の補正
Lesson17
//楕円の角度
let angle =ell.angle;
//ライトセイバーの向きを反転
if(angle<90){ angle=angle-180; }
//デフォルトサイズを元画像の2倍くらいにしたい。
let mul = (ell.size.width*2.0)/beam.width;
//位置指定
canvasCtx.translate(ell.center.x, ell.center.y);
//角度指定
canvasCtx.rotate(angle * Math.PI /180.0);
//楕円を描画
canvasCtx.beginPath();
canvasCtx.ellipse(0, 0, ell.size.width/2.0, ell.size.height/2.0,
0, 0, 2 * Math.PI);
canvasCtx.stroke();
//デフォルトサイズに倍数をかける
canvasCtx.scale(mul, mul);
canvasCtx.drawImage(beam, -beam.width/2.0, 0,
beam.width, beam.height);
あらかじめx方向に半分ずらす
- 81.
- 82.
- 83.
- 84.
親指の状態の計算
let canvasElement;
let canvasCtx;
letbeam; //ライトセイバー的な画像
let ell; //手の位置や傾きを表す楕円
let ratio; //親指の立ち具合を保持
//初期化
window.onload = function() {
//画像の読み込み
beam = loadImage('画像のURL');
let videoElement = document.getElementById('input_video’);
canvasElement = document.getElementById('output_canvas');
canvasCtx = canvasElement.getContext('2d');
//HandTrackingを使用するための関連ファイルの取得と初期化
const hands = new Hands({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
/*以下省略*/
Lesson18
- 85.
- 86.
- 87.
親指の状態を反映
Lesson19
function drawLightSaber(){
//楕円の角度
let angle= ell.angle;
//ライトセイバーの向きを反転
if(angle<90){ angle=angle-180; }
//デフォルトサイズを元画像の2倍くらいにしたい。
let mul = ratio * (ell.size.width*2.0)/beam.width;
//位置指定
canvasCtx.translate(ell.center.x, ell.center.y);
//角度指定
canvasCtx.rotate(angle * Math.PI /180.0);
//楕円を描画
canvasCtx.beginPath();
canvasCtx.ellipse(0, 0, ell.size.width/2.0, ell.size.height/2.0,
0, 0, 2 * Math.PI);
canvasCtx.stroke();
/*スペースの都合により省略*/
}
親指の立ち具合をかける
- 88.