catalinaの備忘録

ソフトウェアやハードウェアの備忘録。後で逆引きできるように。

Hololensでカメラを扱う[c++/UWP]

HoloLensにはカメラが搭載されているので、どんなもんが載ってるか調べてみようと思います。かたりぃなです。

(2017/02/26更新) Hardware detailsのURLを追記。

HoloLensのカメラって?

公式サイト

https://developer.microsoft.com/en-us/windows/holographic/hardware_details#pagenotfound

ここからUnderstanding HoloLens->Hardware detailsで詳細を見れますが現時点ではリンク切れになってしまっています。(2017/02/09 17:00現在) まあ、無いものねだりしても仕方ないので、そのうち復旧することを祈りつつソフトウェア側から攻めることにします。

(2017/02/26更新) URL更新されているとのコメントいただきました。現在はHoloLens hardware detailsでアクセスできました。

結論

手元のHoloLens上でデバイスを列挙してプレビューの開始をしてみたところ、"MN34150"という型番のデバイスが1個だけ列挙されました。

型番調べてみたところ、これっぽいです。 MN34150 | 製品 | 半導体 | Panasonic

列挙されたデバイスの物理的な場所はHololens正面の鼻あての上あたりでした。(カメラの前に手をかざしてプレビュー見ながら確認)

UWPでのカメラ操作

まずUWPでのカメラAPIは2種類存在しています。

  1. CameraCaptureUI
  2. MediaCapture

1はカメラを操作するUIも含めて提供されている高レベルAPIです。 インスタンス作って呼びだせば写真撮影のUIが起動します。

2は1と比べると低レベルなAPIで、デバイスの列挙、カメラの準備、プレビュー開始、撮影など細かく制御できます。 中身はMediaFoundationらしく、MediaTransferのインターフェイスをもったエフェクトの挿入などもできるようです。 今回はこれを使ってHoloLensのデバイスを列挙してみます。

詳細なドキュメントはそれぞれ以下になります。

MediaCapture class - UWP app developer | Microsoft Docs

CameraCaptureUI Class (Windows)

DeviceInformationを使ってカメラデバイスを列挙する

まずMainPageのクラス定義に以下を追加します。列挙されたデバイスを保持しておくためのものです。

DeviceInformationCollection^ m_devInfoCollection;

そして初期化コードに以下のものを埋め込みます。ほとんどサンプルコードのままです。

いつもどおりcreate_taskで生成したタスクの実行が完了すると、then節のラムダが起動します。ラムダ内で列挙されたデバイスをごにょごにょします。 このAPIは列挙されたデバイス個別にコールバックするのではなくまとめてコレクション返してくる仕様のようです。

 m_devInfoCollection = nullptr;

    EnumedDeviceList2->Items->Clear();

    create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture)).then([this](task<DeviceInformationCollection^> findTask)
    {
        m_devInfoCollection = findTask.get();
        for (unsigned int i = 0; i < m_devInfoCollection->Size; i++){
            auto devInfo = m_devInfoCollection->GetAt(i);
            auto location = devInfo->EnclosureLocation;

            if (location != nullptr){

                if (location->Panel == Windows::Devices::Enumeration::Panel::Front){
                    EnumedDeviceList2->Items->Append(devInfo->Name + "-Front");
                }
                else if (location->Panel == Windows::Devices::Enumeration::Panel::Back){
                    EnumedDeviceList2->Items->Append(devInfo->Name + "-Back");
                }
                else {
                    EnumedDeviceList2->Items->Append(devInfo->Name);
                }
            }else {
                EnumedDeviceList2->Items->Append(devInfo->Name);
            }
        }
        EnumedDeviceList2->SelectedIndex = 0;
    });

プレビュー機能を実装する

プレビューにメディアキャプチャクラスを使うので、MainPageの定義に以下の変数を追加します。

 Platform::Agile<Windows::Media::Capture::MediaCapture> m_mediaCaptureMgr;

プレビュー対象CaptureElementというものを使えばいいらしいのでXAMLに適当に定義します。 これとは別に適当にボタン貼っておいて、そのイベントハンドラをプレビューの起動トリガに使います。

        <Canvas x:Name="previewCanvas2" Width="320"  Height="240" Background="Gray" Margin="110,220,423,20">
            <CaptureElement x:Name="previewElement2" Width="320" Height="240" />
        </Canvas>

ボタンのイベントハンドラに以下のようなコードを入れます。 エラーチェックはしていません。

 m_mediaCaptureMgr = ref new Windows::Media::Capture::MediaCapture();

    auto settings = ref new Windows::Media::Capture::MediaCaptureInitializationSettings();
    auto chosenDevInfo = m_devInfoCollection->GetAt(EnumedDeviceList2->SelectedIndex);
    settings->VideoDeviceId = chosenDevInfo->Id;
    settings->StreamingCaptureMode = Capture::StreamingCaptureMode::AudioAndVideo;

    create_task(m_mediaCaptureMgr->InitializeAsync(settings))
    .then([this](task<void> initTask)
    {
        auto mediaCapture = m_mediaCaptureMgr.Get();
        previewCanvas2->Visibility = Windows::UI::Xaml::Visibility::Visible;
        previewElement2->Source = mediaCapture;
        create_task(mediaCapture->StartPreviewAsync());
    });

最後にPackage.appmanifestのWebカメラとマイクをONにしてビルド。エミュレータでやっても意味がないので実機でやります。

実行結果

  • 列挙されたデバイス : MN34150-back
  • プレビュー:表示された

というわけで、デバイス名とカメラの向き(front/back)まで調べてプレビュー表示できました。 もっといっぱいカメラを列挙できるかと思いましたが、1個しかなくて残念です。 (スペック表には4つの環境カメラや空間認識カメラなど載っていた気がしたのですが、今回のAPIでは取れないようです。)

どうしてback?

カメラのプロパティにbackというのがついてきます。これはカメラの向きの定義が「使用者のほうを向いているほうがfront」「反対方向がback」だからのようです。 ノートパソコンで画面と同じ向きに取り付けられているカメラはfrontで、画面と反対方向(メーカーのロゴとか入ってるほう)はbackだと考えると、まあ納得できます。 ちなみにUSBカメラはどっちでもないようです(そりゃ向きを自由に変えられるのだからfrontもbackもありませんよね。)

感想と今後の展望

やっとHoloLensでMR的なことをやる道具が揃い始めました。 MediaFoundationの近くまで進んだので、次回はMediaFoundationで画像処理を行って、その結果を取り出したいと思います。