> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dwe.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 複数カメラのフレーム同期

> stellarHD カメラを同期する方法のガイドです。

<Icon icon="triangle-person-digging" color="#FFC107" iconType="regular" size={32} /> ***このドキュメントは現在改善中であり、作成中です!***

<Note>
  **電気的**および**ソフトウェア的**同期の両方が必要です。詳細な手順については以下を参照してください。
</Note>

# 電気配線ガイド

<Tabs>
  <Tab title="Leader-Follower モード">
    ## 概要

    このモードは、**外部クロック信号を使用しない**構成向けに設計されています。

    1 台のカメラを `leader` モード(同期信号を出力)で、残りのすべてのカメラを `follower` モードで使用します。

    <Card title="Leader/Follower ファームウェアガイド" icon="link" href="/ja/stellarHD/guides/stellarHD-firmware">
      カメラを Leader モードと Follower モードの間で更新する方法のガイドはこちらをクリックしてください。
    </Card>

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-light.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=4c5823a5d745629d5a62fb7dd84a1a49" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-light.svg" />

      <img className="hidden dark:block" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-dark.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=1ae7234422717f420009665eb9043f22" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-dark.svg" />
    </Frame>

    ***

    ## 配線

    <Frame>
      <img width="800px" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Diagram.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=5b0ab2de70b284309a3f13901f0a77b9" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Diagram.svg" />
    </Frame>

    ### 例

    <Frame caption="フレーム同期のために 2 台のカメラから配線が接続された例。">
      <img width="400px" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Example.jpg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=8fedebc8290229dd132d773e49a63a49" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Example.jpg" />
    </Frame>
  </Tab>

  <Tab title="Follower-Only モード(外部クロック)">
    ## 概要

    このモードは、すべてのカメラに対して同期信号を出力するために**外部クロック信号を使用する**構成向けに設計されています。

    このモードでは、すべてのカメラを `follower` モードに設定する必要があります。

    <Card title="Leader/Follower ファームウェアガイド" icon="link" href="/ja/stellarHD/guides/stellarHD-firmware">
      カメラを Leader モードと Follower モードの間で更新する方法のガイドはこちらをクリックしてください。
    </Card>

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-light.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=362833b4adcee1048a3833f297c67770" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-light.svg" />

      <img className="hidden dark:block" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-dark.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=fd356395a3435524d7647e4928f2126c" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-dark.svg" />
    </Frame>

    ***

    ## 配線

    外部フレーム同期仕様については、お使いの特定デバイスの製品ページを確認してください。

    <Frame>
      <img width="800px" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Wiring-Diagram.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=b49517610c550da641202bb88f6441ab" data-path="stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Wiring-Diagram.svg" />
    </Frame>

    ***

    ## 外部クロック信号の生成

    ### Arduino との統合

    <Note>
      この構成で *確認済み* に動作するボードは、現時点では **Arduino Uno (ATmega328P)** のみです。
    </Note>

    <Steps>
      <Step title="PWM ライブラリをダウンロード">
        PWM ライブラリのソースコードはこちらからダウンロードしてください: [ArduinoPWM v1.0.0](https://github.com/DeepWaterExploration/ArduinoPWM/archive/refs/tags/v1.0.0.zip)
      </Step>

      <Step title=".ZIP ライブラリを追加">
        ダウンロードした `.ZIP` ライブラリを Arduino IDE にインポートします。

        <Frame>
          <img src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/ArduinoPWM-Library.png?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=ae6bb3c799a2b3d3dba92d8696fa9dce" width="1210" height="933" data-path="stellarHD/guides/images/syncing-multiple-cameras/ArduinoPWM-Library.png" />
        </Frame>
      </Step>

      <Step title="スケッチをアップロード">
        以下の 2 つのスケッチのいずれかを Arduino にアップロードします。

        * **シンプル制御:** 最も簡単に始められますが、FPS を調整するにはファームウェアを再書き込みする必要があります。
        * **シリアル制御:** 再書き込みなしで周波数とデューティサイクルをリアルタイムで調整できます(デバイスの電源が切れると設定はリセットされます)。

        <Tabs>
          <Tab title="シンプル制御">
            ```cpp theme={null}
            #include <PWM.h>

            // ピン構成
            int pin = 9;       // ピン
            int value = 127;   // PWM デューティサイクルの初期値

            // ここで周波数を設定
            float frequency = 60; // 初期周波数(Hz)

            void setup()
            {
                // 時間計測タスクを保護するため、timer0 以外のすべてのタイマーを初期化
                InitTimersSafe();

                // 初期 PWM 周波数とデューティサイクルを設定
                if (SetPinFrequencySafe(pin, frequency))
                {
                    pwmWrite(pin, value);
                    Serial.println("PWM frequency and initial duty cycle set.");
                }
                else
                {
                    Serial.println("Failed to set frequency.");
                }
            }
            ```
          </Tab>

          <Tab title="シリアルコマンド">
            ```cpp theme={null}
            #include <PWM.h>

            // ピン構成
            int pin = 9;          // ピン
            int value = 127;      // PWM デューティサイクルの初期値
            float frequency = 60; // 初期周波数(Hz)

            void setup()
            {
                Serial.begin(9600);

                // 時間計測タスクを保護するため、timer0 以外のすべてのタイマーを初期化
                InitTimersSafe();

                // 初期 PWM 周波数とデューティサイクルを設定
                if (SetPinFrequencySafe(pin, frequency))
                {
                    pwmWrite(pin, value);
                    Serial.println("PWM frequency and initial duty cycle set.");
                }
                else
                {
                    Serial.println("Failed to set frequency.");
                }
            }

            void loop()
            {
                if (Serial.available())
                {
                    // Serial から周波数とデューティサイクル値を読み取る
                    String inputString = Serial.readStringUntil('\n'); 
                    inputString.trim();                                
                    int freqDutySplitIndex = inputString.indexOf(',');

                    if (freqDutySplitIndex != -1)
                    {
                        String freqStr = inputString.substring(0, freqDutySplitIndex);  
                        String dutyStr = inputString.substring(freqDutySplitIndex + 1); 

                        // float をパース
                        float newFrequency = freqStr.toFloat();
                        int newDutyCycle = dutyStr.toInt();

                        // 周波数範囲を検証
                        if (newFrequency >= 1 && newFrequency <= 2000000)
                        {
                            // PWM 周波数を設定し、デューティサイクルを適用
                            if (SetPinFrequencySafe(pin, newFrequency))
                            {
                                value = map(constrain(newDutyCycle, 0, 100), 0, 100, 0, 255);
                                pwmWrite(pin, value);
                                Serial.print("Set frequency to: ");
                                Serial.print(newFrequency);
                                Serial.print(" Hz, duty cycle to: ");
                                Serial.print(newDutyCycle);
                                Serial.println("%");
                            }
                            else
                            {
                                Serial.println("Failed to set new frequency.");
                            }
                        }
                        else
                        {
                            Serial.println("Invalid frequency value.");
                        }
                    }
                    else
                    {
                        Serial.println("Invalid input format. Use frequency,dutycycle (e.g., 60,50).");
                    }
                }
            }
            ```

            このコードを使用すると、PWM 信号をその場で変更できます。シリアルモニタを `9600` ボーで開き、`{FREQUENCY},{DUTY_CYCLE}` の形式でコマンドを送信します(例: 60Hz、デューティサイクル 50% の場合は `60,50`)。
          </Tab>
        </Tabs>
      </Step>
    </Steps>
  </Tab>
</Tabs>

***

## 同期ビデオ Python ライブラリ(Linux)

近日公開予定の SDK に加えて、現在、カメラセットアップから同期されたフレームを取得するためのシンプルな Python プロセスを提供しています。*(注意: これは将来的に、フル機能の SDK に置き換えられる場合があります。)*

<Card title="同期ビデオ Python ライブラリ" icon="github" href="https://github.com/DeepWaterExploration/synchronized_camera_python">
  GitHub ガイドに従って、当社のカスタム Linux Python ライブラリをインストールおよび使用してください。
</Card>

***

## 同期されたスティッチビデオ

ここでは、GStreamer を使用して 2 つのビデオフィードを同期しスティッチする方法と、その後他のプログラムで使用するための仮想デバイスを作成する方法について説明します。

<Tabs>
  <Tab title="Linux">
    <Steps>
      <Step title="必要なパッケージをインストール">
        次のコマンドを使用して必要な依存関係をインストールします:

        ```bash theme={null}
        sudo apt install -y libx264-dev libjpeg-dev \
        libglib2.0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
        gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
        gstreamer1.0-plugins-bad gstreamer1.0-libav libgstreamer-plugins-bad1.0-dev \
        gstreamer1.0-plugins-ugly gstreamer1.0-gl \
        v4l-utils
        ```
      </Step>

      <Step title="現在のカメラデバイスを一覧表示">
        次のコマンドを実行して、接続されているカメラを確認します:

        ```bash theme={null}
        v4l2-ctl --list-devices
        ```

        **出力例:**

        ```text theme={null}
        stellarHD Leader: stellarHD Lea (usb-0000:00:14.0-8.3):
            /dev/video0
            /dev/video1
            /dev/media0

        stellarHD Follower: stellarHD F (usb-0000:00:14.0-8.4):
            /dev/video2
            /dev/video3
            /dev/media1
        ```
      </Step>

      <Step title="仮想デバイスを作成">
        使用する 2 台のカメラのデバイス ID を特定し、現在リストに**ない**デバイス ID 番号を選択します。

        この例では、`9`(上記で未使用)を使用して `stellarHD_stitched` という仮想デバイスを作成します。以下のコマンドの `9` を選択した未使用 ID に置き換えてください:

        ```bash theme={null}
        sudo modprobe v4l2loopback video_nr=9 \
        card_label=stellarHD_stitched exclusive_caps=1
        ```
      </Step>

      <Step title="GStreamer パイプラインを起動">
        スティッチビデオを作成し、ストリームを新しい仮想デバイスに出力するパイプラインを起動します:

        ```bash theme={null}
        gst-launch-1.0 -v \
        compositor name=mix \
            sink_0::xpos=0    sink_0::ypos=0   sink_0::alpha=1 \
            sink_1::xpos=1600 sink_1::ypos=0   sink_1::alpha=1 \
        ! jpegenc ! jpegdec ! videoconvert ! v4l2sink device=/dev/video9 \
        v4l2src device=/dev/video0 ! image/jpeg,width=1600,framerate=60/1 ! jpegdec ! videorate ! mix.sink_0 \
        v4l2src device=/dev/video2 ! image/jpeg,width=1600,framerate=60/1 ! jpegdec ! videorate ! mix.sink_1
        ```

        <Note>
          同期したスティッチビデオを使用している間は、このコマンドを実行し続ける必要があります。このコマンドを変更して、カメラを追加したり、解像度/フレームレートを変更したり、レイアウトを変更したりできます。
        </Note>
      </Step>

      <Step title="OpenCV で仮想デバイスを使用">
        <Card title="OpenCV スターターコード" icon="github" href="https://github.com/DeepwaterExploration/opencv-guides">
          サンプルコードに従って、OpenCV で `/dev/video9` を使用します。
        </Card>
      </Step>

      <Step title="ループバックデバイスを削除">
        ループバックデバイスを安全に削除するには、コンピューターを再起動するか、次のコマンドを順番に実行できます:

        **1. 現在ループバックデバイスを使用しているプログラムを特定:**

        ```bash theme={null}
        sudo lsof /dev/video*
        ```

        **2. PID(プロセス ID)番号を使用してプロセスを終了:**

        ```bash theme={null}
        sudo kill <INSERT_PID_NUMBER>
        ```

        **3. ループバックデバイスを削除:**

        ```bash theme={null}
        sudo modprobe -r v4l2loopback
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>
