我有五台 USB 摄像头,品牌和型号相同(Canyon CNR-FWC120H)。它们用于全天候监控不同的场景。我需要以某种方式从 Linux(Debian)控制台或以编程方式(任何语言)识别哪个摄像头是哪个。
我尝试查看的输出lsusb -vvv
,有一个字段iSerial
对于每个相机应该是不同的,但不幸的是,这个制造商决定不去理会,并且所有相机在那个位置都有相同的序列号:200901010001
有没有其他方法可以让我识别哪个摄像头是哪个摄像头,而不依赖于它们所连接的 USB 端口,因为不幸的是,在我的特定场景中,我不能依赖于同一台摄像头总是连接到同一个端口这一事实。
更新在评论中讨论后,我意识到这是不可能完成的任务。所以请忘掉最后一段,或者如果你确实有一些巧妙的想法,欢迎提出来。我现在感兴趣的是,我是否可以识别设备连接到哪个 USB 端口;我使用主板上的内置 USB 端口和附加的 PCI USB 控制器卡来为相机提供足够的带宽。我需要唯一地标识端口,并且如果例如机器重新启动并且由于某种原因 USB 控制器以不同的顺序初始化,端口号/标识不应改变。这可能吗?
更新2我在其中一个摄像机的日志中看到以下信息:
[Wed Apr 30 18:35:02 2014] uvcvideo: Found UVC 1.00 device FULL HD 1080P Webcam (0bda:58b0)
[Wed Apr 30 18:35:02 2014] input: FULL HD 1080P Webcam as /devices/pci0000:00/0000:00:01.0/0000:01:00.0/usb3/3-2/3-2:1.0/input/input4
使用它,我调用了这个命令:
udevadm info --query=all --path=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/usb3/3-2/3-2:1.0/input/input4
并得到这个:
P: /devices/pci0000:00/0000:00:01.0/0000:01:00.0/usb3/3-2/3-2:1.0/input/input4
E: DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/usb3/3-2/3-2:1.0/input/input4
E: EV=3
E: ID_BUS=usb
E: ID_INPUT=1
E: ID_INPUT_KEY=1
E: ID_MODEL=FULL_HD_1080P_Webcam
E: ID_MODEL_ENC=FULL\x20HD\x201080P\x20Webcam
E: ID_MODEL_ID=58b0
E: ID_PATH=pci-0000:01:00.0-usb-0:2:1.0
E: ID_PATH_TAG=pci-0000_01_00_0-usb-0_2_1_0
E: ID_REVISION=5801
E: ID_SERIAL=Generic_FULL_HD_1080P_Webcam_200901010001
E: ID_SERIAL_SHORT=200901010001
E: ID_TYPE=video
E: ID_USB_DRIVER=uvcvideo
E: ID_USB_INTERFACES=:0e0100:0e0200:010100:010200:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=Generic
E: ID_VENDOR_ENC=Generic
E: ID_VENDOR_ID=0bda
E: KEY=100000 0 0 0
E: MODALIAS=input:b0003v0BDAp58B0e5801-e0,1,kD4,ramlsfw
E: NAME="FULL HD 1080P Webcam"
E: PHYS="usb-0000:01:00.0-2/button"
E: PRODUCT=3/bda/58b0/5801
E: PROP=0
E: SUBSYSTEM=input
E: UDEV_LOG=3
E: USEC_INITIALIZED=41090223
相机之间的不同之处在于DEVPATH
,,,ID_PATH
和(最有趣的)。现在前四个元素可能与 USB 端口有关,但最后一个看起来像某种序列号。我找不到任何关于它实际代表什么的ID_PATH_TAG
信息。有人知道吗?我认为这可能是相机初始化时的微秒时间,但在这台相机之后初始化的相机有,然后是下一台,所以它看起来相当随机。我会尝试重新启动系统并查看,但我需要等待方便的时间来执行此操作。PHYS
USEC_INITIALIZED
USEC_INITIALIZED
USEC_INITIALIZED=17919751
USEC_INITIALIZED=25609278
如果有人想知道为什么我不尝试重新连接相机,看看情况是否仍然一样。答案是我正在远程操作这台电脑,我正在调查这一切,以便让系统为未来可能发生的任何事件做好完全自主的准备。例如,这可能包括断开相机与 USB 端口的连接。
答案1
摄像机的位置是否固定?场景是否基本固定?如果是这样,您可以使用图像识别来根据摄像机看到的内容来识别它们。
有一些不错的 Python 工具可以做到这一点,这个答案对这个主题有一些很好的信息:https://stackoverflow.com/questions/1927660/compare-two-images-the-python-linux-way
答案2
正如您所发现的,如果您无法从设备本身获得唯一标识,则无法解决问题。最接近解决方案的方法是依靠设备的物理连接。(这不会在重启时改变。只有当您物理更改连接器的位置时才会改变)
您可以通过编程方式使用 sysfs 获取内核拥有的有关设备的信息。Sysfs 是内核看到的设备的一种文件系统式表示。(它不是磁盘上的真实文件)
有了它,您可以: - 使用产品和供应商 ID 识别设备类型 - 读取设备的序列号(如果有)。 - 读取 USB 集线器上的物理连接号
您可以先在 /sys/class 中查找设备类型。在此示例中,我使用 USB→LPT 端口。但原理是一样的。
$ ls -l /sys/class/usbmisc
lp1 -> ../../devices/pci0000:00/0000:00:1d.0/usb4/4-1/4-1.5/4-1.5:1.0/usbmisc/lp1
lp2 -> ../../devices/pci0000:00/0000:00:1d.0/usb4/4-1/4-1.6/4-1.6:1.0/usbmisc/lp2
从 uevent 文件中获取设备名称:
cat /sys/class/usbmisc/lp1/uevent
MAJOR=180
MINOR=1
DEVNAME=__usb/lp1__
添加 /dev 以便获取要打开的设备名称:/dev/usb/lp1
使用真实路径:$ cd -P /sys/class/usbmisc/lp1
后退 3 个分支:
$ cd ../../../
/sys/devices/pci0000:00/0000:00:1d.0/usb4/4-1/4-1.5
该目录包含大量有关设备的信息:
产品编号和供应商编号可用于唯一标识设备类型。
如果有串行文件并且它包含一个唯一的序列号,您就完成了。
否则,您的选择是使用物理连接作为标识,即此目录名称“4-1.5“它对于物理连接来说是独一无二的,并且正如您所提到的,如果您将设备插入另一个端口,它就会发生变化。
答案3
只需拔下相机,插入 1 并执行 lsusb。识别相机并记下使用的 USB 端口。也许在相机上贴一个小标签。然后对其他相机重复此操作,您就会成功。没有什么是不可能完成的任务 ;)
答案4
我听说过有人在启动过程中延迟按顺序打开设备电源,这样您就可以根据设备的打开顺序来识别它们。这需要一些额外的硬件来按顺序控制单个 USB 端口的电源。
您可以破解每个端口都有单独电源开关的 USB 集线器,将其连接到 arduino 并触发它们的打开顺序。