3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

楽しい ニューラルネットワークのゲーム。

Last updated at Posted at 2024-10-12

ショートストーリー: 「眼と脳の計算模型」

祐介は東京に住む若手プログラマだ。毎日、静かな自宅でPCに向かい、新しい技術に触れ、挑戦を続けている。今日の彼のテーマは「Webカメラとニューラルネットワーク」。カメラから映し出されるリアルタイムの映像を、人工知能が「学習」し、まるで人間の眼と脳のように理解できるようにする。彼の仕事はその計算モデルを作り上げることだった。

スクリーンショット 2024-10-13 045647.png

「カメラは人間の眼だ。そこから入ってくる映像をどう処理するか、それが脳の役割だな…」祐介は自分にそう言い聞かせるようにつぶやいた。

彼が目指すのは、Webカメラが映し出す128×128ピクセルの映像をリアルタイムで取得し、それをニューラルネットワークで処理するシステムだ。カメラの映像が脳へと情報を送り込み、それを理解し、反応する。彼が作ろうとしているプログラムは、まさにそのモデルだ。

祐介のコードは、まるで生命を宿すように少しずつ動き始めた。カメラが動き、映像をキャプチャする。祐介は手元にあるWebカメラをのぞき込み、その映像をコードに送り込む。

カメラは彼の部屋を映していた。薄暗い机の上、積み上げられた技術書、そしてその横で光るモニター。祐介は128×128の小さな世界を見つめた。

次に彼は、ニューラルネットワークモデルにその映像を渡す。神経回路のように複雑なモデルが、映像データを受け取り、処理を始める。全結合層型のニューラルネットワークが画像を学習し、予測を繰り返す。

スクリーンショット 2024-10-13 045517.png

「これは脳が考える瞬間だ。」

彼のプログラムが少しずつ現実の映像を学び、予測を生成する。そして、右側のモニターに表示されるのはニューラルネットワークが「考えた」映像。まだぼやけてはいるが、祐介の部屋の形が徐々に浮かび上がってきた。

祐介は、何度もモデルを訓練し続けた。時間が経つにつれ、右側の映像はよりクリアになり、左側の現実の映像と少しずつ似てくる。

「眼が見たものを脳が理解する…これはまるで、人間の感覚そのものだ。」

祐介はふと、何かに気づいた。彼が作っているのはただのプログラムではなかった。これは、まるで人間の「見る」という行為そのものを再現する計算模型だ。人間の眼と脳が連携し、現実を認識するように、彼のコードはカメラの映像をニューラルネットワークで理解しようとしている。

スクリーンショット 2024-10-13 045541.png

深夜、彼のプログラムは完璧に動いていた。左側に映し出された現実の世界、そして右側に表示されるニューラルネットワークの「脳」が見た世界。祐介は静かに笑みを浮かべた。

「これが眼と脳の計算模型だ。」彼は言った。

彼が作り出したのは、まるで生き物のように感じるプログラムだった。現実の映像を目で見て、脳がその情報を処理して理解する。シンプルな数行のコードが、生物の知覚を模倣する瞬間に祐介は立ち会っていた。

祐介は東京の夜を見つめた。彼の頭の中では、次の挑戦へのアイデアが沸き上がっていた。彼の旅はまだ続く。彼の眼と脳を持つプログラムが、どこまで進化できるかは、これからの彼次第だった。

スクリーンショット 2024-10-13 045647.png

スクリーンショット 2024-10-13 045517.png

スクリーンショット 2024-10-13 045541.png

Webカメラの映像をキャプチャし、ニューラルネットワークでトレーニングした後、モデルの出力を画面の右側に拡大して表示するものです。

Webカメラから取得した映像が左側に128×128ピクセルで表示され、ニューラルネットワークの予測出力が右側に512×512ピクセルに拡大されて表示されます。

機能の説明

継続的なトレーニングと予測: trainAndDisplay関数は、Webカメラの現在のフレームをニューラルネットワークに入力し、1エポックでトレーニングした後にその出力を右側のキャンバスに描画します。このプロセスがrequestAnimationFrameによって継続的に繰り返されるため、トレーニングが進むにつれて、右側の出力が段々と変化していくアニメーションのように表示されます。

アニメーション効果: Webカメラの映像をリアルタイムでニューラルネットワークに入力し、トレーニングし続けることで、モデルの出力が右側に表示され、時間とともに変化する様子が確認できます。

コードをメモ帳などのテキストエディタに貼り付け、ファイル名を「index.html」として保存します。その後、保存したファイルをブラウザで開けば、コードが実行されます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Webカメラとニューラルネットワークのアニメーション</title>
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
    <style>
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <h1>Webカメラとニューラルネットワークの出力</h1>
    <div style="display: flex; gap: 20px;">
        <!-- 左側にWebカメラの映像を表示 -->
        <video id="webcam" autoplay playsinline width="128" height="128"></video>

        <!-- 右側にニューラルネットワークの出力を表示(拡大版) -->
        <canvas id="outputCanvas" width="512" height="512"></canvas>
    </div>

    <script>
        // Webカメラのセットアップ関数
        async function setupWebcam() {
            const webcamElement = document.getElementById('webcam');
            return new Promise((resolve, reject) => {
                const constraints = {
                    video: { width: 128, height: 128 } // 128×128の解像度でWebカメラを設定
                };
                navigator.mediaDevices.getUserMedia(constraints)
                    .then((stream) => {
                        webcamElement.srcObject = stream; // Webカメラの映像をvideo要素にセット
                        webcamElement.addEventListener('loadeddata', () => resolve(webcamElement)); // 映像がロードされたら解決
                    })
                    .catch(reject); // エラー時にはreject
            });
        }

        async function run() {
            const webcam = await setupWebcam(); // Webカメラをセットアップ

            // シンプルなニューラルネットワークモデルの作成
            const model = tf.sequential();
            model.add(tf.layers.dense({
                units: 64,
                inputShape: [128 * 128 * 3], // 入力は128×128ピクセル×3チャンネル
                activation: 'relu' // 活性化関数にReLUを使用
            }));
            model.add(tf.layers.dense({
                units: 128 * 128 * 3, // 出力も128×128ピクセル×3チャンネル
                activation: 'sigmoid' // 活性化関数にSigmoidを使用(出力は0~1にスケール)
            }));
            model.compile({
                optimizer: 'adam', // Adamオプティマイザ
                loss: 'meanSquaredError' // 損失関数は平均二乗誤差
            });

            // Webカメラの現在のフレームをキャプチャする関数
            function captureFrame() {
                const canvas = document.createElement('canvas');
                canvas.width = 128;
                canvas.height = 128;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(webcam, 0, 0, 128, 128); // Webカメラのフレームをキャンバスに描画
                const imageData = ctx.getImageData(0, 0, 128, 128); // 画像データを取得

                // RGBAデータをRGBに変換(アルファチャンネルは無視)
                const rgbData = new Uint8Array(128 * 128 * 3);
                for (let i = 0; i < 128 * 128; i++) {
                    rgbData[i * 3] = imageData.data[i * 4];       // 赤チャンネル
                    rgbData[i * 3 + 1] = imageData.data[i * 4 + 1]; // 緑チャンネル
                    rgbData[i * 3 + 2] = imageData.data[i * 4 + 2]; // 青チャンネル
                }

                // データをテンソルに変換し、0-1の範囲にスケーリング
                return tf.tensor(rgbData, [1, 128 * 128 * 3]).div(255);
            }

            // モデルをトレーニングし、結果を表示する関数
            async function trainAndDisplay() {
                const inputFrame = captureFrame(); // 現在のWebカメラのフレームを取得

                // モデルをトレーニング(1エポック)
                await model.fit(inputFrame, inputFrame, { epochs: 1 });

                // モデルの出力を予測
                const output = model.predict(inputFrame).reshape([128, 128, 3]); // 出力を128x128x3にリシェイプ

                // 出力キャンバスにモデルの出力を描画
                const outputCanvas = document.getElementById('outputCanvas');
                const outputCtx = outputCanvas.getContext('2d');
                const outputImageData = outputCtx.createImageData(128, 128); // 128x128の空のイメージデータを作成
                const data = await output.data(); // モデルの出力データを取得

                // RGBデータをImageData形式に変換
                for (let i = 0; i < 128 * 128; i++) {
                    outputImageData.data[i * 4] = data[i * 3] * 255;     // 赤チャンネル
                    outputImageData.data[i * 4 + 1] = data[i * 3 + 1] * 255; // 緑チャンネル
                    outputImageData.data[i * 4 + 2] = data[i * 3 + 2] * 255; // 青チャンネル
                    outputImageData.data[i * 4 + 3] = 255; // アルファチャンネル(完全不透明)
                }

                // 128x128のデータを一度キャンバスに描画
                const tempCanvas = document.createElement('canvas');
                tempCanvas.width = 128;
                tempCanvas.height = 128;
                const tempCtx = tempCanvas.getContext('2d');
                tempCtx.putImageData(outputImageData, 0, 0); // 一度元のサイズで描画

                // その後、512x512に拡大して表示
                outputCtx.drawImage(tempCanvas, 0, 0, 128, 128, 0, 0, 512, 512); // 拡大描画

                // 継続的にトレーニングと描画を行う
                requestAnimationFrame(trainAndDisplay);
            }

            // トレーニングと表示のループを開始
            trainAndDisplay();
        }

        // プログラムを実行
        run();
    </script>
</body>
</html>

3
5
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
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?