如何使用OpenCvSharp4查找可用网络摄像头的索引?

nwnhqdif  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(456)

后台

我正在开发一个C# WinForms应用程序,它使用OpenCvSharp4从一个或多个连接的网络摄像头按需捕获图像。
我目前有代码,从第一个相机使用var capture = new VideoCapture(0)捕获。这对第一个连接的相机(即索引0)非常有效,如果相机连接,我手动指定的任何其他索引。

提问

我希望每个部署都能动态选择要捕获的摄像头。除了反复试验,我如何找到当前系统上所有可用摄像头的索引以便创建摄像头索引列表,以便稍后循环使用?

预期用途

我希望用它来做这样的事情:

void main()
{
  var cameras = GetAvailableCameras();
  foreach (var idx in cameras)
  {
    var capture = VideoCapture(idx);
    // capture the image...
  }
}

IEnumerable<int> GetAvailableCameras()
{
  // do something here to get the available indexes
}

注意事项
为了保持程序尽可能的精简,我想避免添加任何额外的第三方库,这就是为什么我没有使用AForge.Net,即使我知道有发布的解决方案使用该库。
我会考虑添加额外的微软库,如果它简化的事情。

5uzkadbs

5uzkadbs1#

系统摄像头列表中的INDEXES是否与OpenCvSharp访问的摄像头不匹配?

我发现了OpenCvSharp的一个非常奇怪的行为,以及纠正它的方法。
为了创建一个VideoCapture对象,你需要提供一个“摄像机索引”。理论上,这个索引应该与系统提供的摄像机列表上的索引相匹配(如stackoverflow.com/a/62555468/1599751中所解释的)。然而,如果系统具有“默认”相机,则OpenCvSharp将考虑相机索引0,滑动其余相机索引。因此,如果系统给你这个摄像头列表:
1.摄像机0
1.一号摄影机
1.摄像机2(默认)
1.三号摄影机
1.四号摄影机
这就是OpenCvSharp的行为方式:

var cap0 = new VideoCapture(0); // Opens camera 2 !!
var cap1 = new VideoCapture(1); // Opens camera 0 !!
var cap2 = new VideoCapture(2); // Opens camera 1 !!
var cap3 = new VideoCapture(3); // Opens camera 3
var cap4 = new VideoCapture(4); // Opens camera 4

VideoCapture.Open的文档将index参数描述为:
要打开的视频捕获设备的ID。要使用默认后端打开默认相机,只需传递0。(为了向后兼容,当apiPreference为CAP_ANY时,camera_id + domain_offset(CAP_*)的用法有效)。
这对我来说有点晦涩,因为我找不到任何关于 domain_offset 是什么的解释。(至少在我的电脑上)你也可以通过添加700来创建VideoCapture对象(或1400)到索引。而且在这样做的时候,索引确实与来自系统的索引相匹配。这些都不是“将默认相机发送到顶部”的业务。

var cap0 = new VideoCapture(700); // Opens camera 0
var cap1 = new VideoCapture(701); // Opens camera 1
var cap2 = new VideoCapture(702); // Opens camera 2
var cap3 = new VideoCapture(703); // Opens camera 3
var cap4 = new VideoCapture(704); // Opens camera 4

如果有人知道这个domain_offset是如何工作的,请告诉我们。

相关问题