LoginSignup
2
4

More than 1 year has passed since last update.

macのOpenCVのカメラID

Last updated at Posted at 2021-04-28

OpenCVのカメラに関する困りごと

  • コードを変えていないのに、カメラが別のカメラに切り替わってしまう!
  • チームメンバーの環境で試してもらうときに、独自定数 camera_device_index をいくつか試すように伝えないといけない!
  • system_profiler -json SPCameraDataTypeを使えばデバイスリストを取得できると聞いたのに、異なるカメラに接続されてしまうケースが頻発!

swiftスクリプトでデバイスリストを取得できます!

私が公開しているこのスクリプトで信頼できるリストがつくれます!

  • 使い方は簡単、
    • swift ./avfcam_list.swiftと呼ぶだけでリストのJSONが出力されます。
    • あとはjqコマンドで整形するもよし、pythonでそのまま受け取るもよし、自由にこの出力を使えばokです。
$ swift ./avfcam_list.swift
{
  "SPCameraDataType" : [
    {
      "_name" : "FaceTime HDカメラ(内蔵)",
      "manufacturer" : "Apple Inc.",
      "spcamera_unique-id" : "0x1420000005acXXXX",
      "spcamera_model-id" : "UVC Camera VendorID_1452 ProductID_34304"
    },
    {
      "_name" : "Logi Capture",
      "manufacturer" : "XSplit Project",
      "spcamera_unique-id" : "{2B297012-XXXX-462D-8EAF-XXXXXXXXXXXX}",
      "spcamera_model-id" : "LogiCapture"
    },
    {
      "_name" : "Logitech StreamCam",
      "manufacturer" : "Unknown",
      "spcamera_unique-id" : "0x1200000046dXXXX",
      "spcamera_model-id" : "UVC Camera VendorID_1133 ProductID_2195"
    }
  ]
}
$

前提

  • macOS (私はmacOS 11.3)
  • OpenCVのcv::VideoCaptureを利用している。
  • Capture API backendsにCAP_ANYCAP_AVFOUNDATIONCAP_FFMPEGを使っている。

仕組み

  • macのcv::VideoCaptureはCapture API backendsに様々なものを利用できるようになっています。(リスト)
  • 特殊な設定をしていなければmacではCAP_ANYにすると、CAP_AVFOUNDATIONCAP_FFMPEGが選択されます。
  • Capture API backendsがどちらであったとしても、macでは最終的にはAVFoundationが使われてビデオキャプチャしています。ffmpegの場合、ffmpegのAVFoundationプラグインが利用されます。
  • したがって、camera_device_indexはAVFoundationのリストと整合すればよいのです。

AVFoundationのカメラデバイスリストの取得方法

  • 残念ながらAVFoundationのカメラデバイスリストを取得できるmac標準のコマンドは存在しないようです。
  • また、AVFoundationそのものをpythonc++から直接使うには骨が折れます。
  • ですが、AVFoundationはswiftからなら非常に簡単に利用できます。
  • またmacではswiftを特殊なビルドなくスクリプトのように利用できます!
  • swiftスクリプトでリストをつくりstdoutに出力しさえすれば、あとはpythonC++からコマンド呼び出ししてstdoutを捕まえてあげればok

SwiftでのAVFoundationのカメラリスト取得コード

  • あまりにも簡単すぎで説明が必要ないですね。メソッドの詳細を知りたい人は検索すればAppleのページで詳しく説明してくれています。
avfcam_list.swift
import AVFoundation

let discovery = AVCaptureDevice.DiscoverySession(
    deviceTypes: [
        AVCaptureDevice.DeviceType.builtInWideAngleCamera,
        AVCaptureDevice.DeviceType.externalUnknown,
    ],
    mediaType: AVMediaType.video,
    position: AVCaptureDevice.Position.unspecified
)

let devices = discovery.devices

所感

  • かなり振り回されました。この半年ひどくハマりました。チームメンバーにも迷惑を掛けたと思います。
  • 結局、OpenCVのコードを追いかけて、ffmpegのコードを追いかけてやっとここまでたどり着きました。どちらもプラグインという概念で拡張しているためコードを追うのは一苦労です。cmakeやconfigureの引数でリンクするコードが変わってしまいます。
  • やっと安心してVideoCaptureを利用できそうです。

参考

2
4
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
2
4