3D空間に入ってしまうゲーム。webカメラでリアルタイム描画。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D空間に人物画像を描画</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/body-pix"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
display: block;
}
#video {
display: none; /* カメラの映像は隠しますが、内部で使用します */
}
</style>
</head>
<body>
<video id="video" width="640" height="480" autoplay></video>
<canvas id="output-canvas" style="display:none;"></canvas>
<script>
let scene, camera, renderer;
let personTexture;
let net;
// Three.jsのシーンを初期化
function initThreeJS() {
scene = new THREE.Scene();
// 背景を緑色に設定
scene.background = new THREE.Color(0x00ff00);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// ウィンドウリサイズ時にレンダラーとカメラのアスペクト比を調整
window.addEventListener('resize', () => {
const width = window.innerWidth;
const height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
// カラフルなボックスを10個作成
const geometry = new THREE.BoxGeometry(1, 1, 1);
for (let i = 0; i < 10; i++) {
const material = new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff });
const cube = new THREE.Mesh(geometry, material);
cube.position.set((Math.random() - 0.5) * 10, (Math.random() - 0.5) * 10, (Math.random() - 0.5) * 10);
scene.add(cube);
}
animate();
}
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
scene.rotation.x += 0.001;
scene.rotation.y += 0.001;
renderer.render(scene, camera);
}
// 人物の画像を平面に描画
function addPersonToScene(texture) {
const geometry = new THREE.PlaneGeometry(3, 4);
const material = new THREE.MeshBasicMaterial({ map: texture, transparent: true });
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
}
// BodyPixのモデルをロード
async function loadBodyPix() {
net = await bodyPix.load();
console.log('BodyPixモデルがロードされました');
}
loadBodyPix();
// Webカメラの映像を取得
async function setupCamera() {
const video = document.getElementById('video');
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
return new Promise(resolve => {
video.onloadedmetadata = () => {
resolve();
};
});
}
// 画像を処理して人物のみを抽出し、背景を緑にする
async function processImage() {
const video = document.getElementById('video');
const outputCanvas = document.getElementById('output-canvas');
const ctx = outputCanvas.getContext('2d');
outputCanvas.width = video.videoWidth;
outputCanvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0);
// セグメンテーションを実行
const segmentation = await net.segmentPerson(outputCanvas);
// 画像のピクセルデータを取得
const imageData = ctx.getImageData(0, 0, outputCanvas.width, outputCanvas.height);
const data = imageData.data;
// セグメンテーション結果に基づいて人物部分を描画し、背景を緑色に設定
for (let i = 0; i < data.length; i += 4) {
const n = i / 4;
if (segmentation.data[n] === 0) {
// 背景部分は緑色に設定 (RGB: 0, 255, 0)
data[i] = 0; // R
data[i + 1] = 255; // G
data[i + 2] = 0; // B
data[i + 3] = 255; // アルファ値(透明度)
}
}
ctx.putImageData(imageData, 0, 0);
// Three.js用のテクスチャとして設定
personTexture = new THREE.Texture(outputCanvas);
personTexture.needsUpdate = true;
// 人物をシーンに追加
addPersonToScene(personTexture);
}
// リアルタイム処理を実行
async function renderLoop() {
await processImage();
requestAnimationFrame(renderLoop); // 次のフレームを処理
}
// Three.jsの初期化とカメラのセットアップ
async function init() {
await setupCamera();
initThreeJS();
renderLoop(); // リアルタイム処理開始
}
init();
</script>
</body>
</html>
Webカメラから顔追跡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Real-time Face Tracking with TensorFlow.js</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface"></script>
<style>
video, canvas {
display: block;
margin: 20px auto;
max-width: 100%;
}
</style>
</head>
<body>
<h1>Real-time Face Tracking with TensorFlow.js</h1>
<!-- Webカメラの映像を表示する -->
<video id="webcam" autoplay playsinline width="640" height="480"></video>
<!-- 顔トラッキング結果を表示するキャンバス -->
<canvas id="faceCanvas" width="640" height="480"></canvas>
<script>
let model;
const video = document.getElementById('webcam');
const canvas = document.getElementById('faceCanvas');
const ctx = canvas.getContext('2d');
// BlazeFaceモデルをロードする関数
async function loadModel() {
model = await blazeface.load();
console.log("BlazeFace model loaded.");
startFaceTracking();
}
// Webカメラ映像を取得する関数
async function setupWebcam() {
return new Promise((resolve, reject) => {
const constraints = {
video: true
};
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
video.srcObject = stream;
video.onloadedmetadata = () => {
resolve(video);
};
})
.catch((err) => {
reject(err);
});
});
}
// 顔をリアルタイムで追跡する関数
async function startFaceTracking() {
await setupWebcam();
video.play();
// リアルタイムで顔を検出し、キャンバスに描画するループ
const detectFaces = async () => {
const returnTensors = false;
const predictions = await model.estimateFaces(video, returnTensors);
// キャンバスをクリアして新たに描画
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
if (predictions.length > 0) {
predictions.forEach(prediction => {
const [startX, startY] = prediction.topLeft;
const [endX, endY] = prediction.bottomRight;
const width = endX - startX;
const height = endY - startY;
// 顔の四角形を描画
ctx.beginPath();
ctx.rect(startX, startY, width, height);
ctx.lineWidth = 2;
ctx.strokeStyle = 'red';
ctx.stroke();
// ランドマーク(目や鼻など)の描画
prediction.landmarks.forEach(landmark => {
ctx.beginPath();
ctx.arc(landmark[0], landmark[1], 5, 0, 2 * Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
});
});
}
requestAnimationFrame(detectFaces);
};
detectFaces();
}
// モデルをロードし、Webカメラをセットアップしてから顔追跡を開始
loadModel();
</script>
</body>
</html>