从接口名称而不是摄像机编号创建 openCV VideoCapture
Create openCV VideoCapture from interface name instead of camera numbers
创建视频捕获的正常方法是这样的:
cam = cv2.VideoCapture(n)
其中n对应/dev/video0
、dev/video1
的个数
但是因为我正在构建一个使用多个摄像头来处理不同事物的机器人,所以我需要确保它被分配给了正确的摄像头,我创建了 udev 规则来创建具有符号 link 的设备每当插入特定相机时,都会连接到正确的端口。
它们似乎在工作,因为当我查看 /dev
目录时,我可以看到 link:
/dev/front_cam -> video1
但是我不确定现在如何实际使用它。
我以为我可以直接从文件名打开它,就好像它是一个视频一样,但是 cam = cv2.VideoCapture('/dev/front_cam')
不起作用。
cv2.VideoCapture('/dev/video1')
也不行
它不会抛出错误,它会 return 一个 VideoCapture 对象,只是没有打开一个对象 (cam.isOpened()
returns False
)。
import re
import subprocess
import cv2
import os
device_re = re.compile("Bus\s+(?P<bus>\d+)\s+Device\s+(?P<device>\d+).+ID\s(?P<id>\w+:\w+)\s(?P<tag>.+)$", re.I)
df = subprocess.check_output("lsusb", shell=True)
for i in df.split('\n'):
if i:
info = device_re.match(i)
if info:
dinfo = info.groupdict()
if "Logitech, Inc. Webcam C270" in dinfo['tag']:
print "Camera found."
bus = dinfo['bus']
device = dinfo['device']
break
device_index = None
for file in os.listdir("/sys/class/video4linux"):
real_file = os.path.realpath("/sys/class/video4linux/" + file)
print real_file
print "/" + str(bus[-1]) + "-" + str(device[-1]) + "/"
if "/" + str(bus[-1]) + "-" + str(device[-1]) + "/" in real_file:
device_index = real_file[-1]
print "Hurray, device index is " + str(device_index)
camera = cv2.VideoCapture(int(device_index))
while True:
(grabbed, frame) = camera.read() # Grab the first frame
cv2.imshow("Camera", frame)
key = cv2.waitKey(1) & 0xFF
首先在USB 设备列表中搜索所需的字符串。获取总线和设备编号。
在 video4linux 目录下找到符号 link。从 realpath 中提取设备索引并将其传递给 VideoCapture 方法。
我找到了一个较短的解决方案,而不是建议的解决方案,感觉有点老套。
我只是看看符号link指向的位置,找到其中的整数,然后使用它。
import subprocess
cmd = "readlink -f /dev/CAMC"
process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
# output of form /dev/videoX
out = process.communicate()[0]
# parse for ints
nums = [int(x) for x in out if x.isdigit()]
cap = cv2.VideoCapture(nums[0])
如果您知道相机的型号,可以在/dev/v4l/by-id/...
中查找。我们正在使用 HDMI-USB 视频转换器,我们这样连接它:
#! /usr/bin/env python
import os
import re
import cv2
DEFAULT_CAMERA_NAME = '/dev/v4l/by-id/usb-AVerMedia_Technologies__Inc._Live_Gamer_Portable_2_Plus_5500114600612-video-index0'
device_num = 0
if os.path.exists(DEFAULT_CAMERA_NAME):
device_path = os.path.realpath(DEFAULT_CAMERA_NAME)
device_re = re.compile("\/dev\/video(\d+)")
info = device_re.match(device_path)
if info:
device_num = int(info.group(1))
print("Using default video capture device on /dev/video" + str(device_num))
cap = cv2.VideoCapture(device_num)
这遵循设备名称符号链接到 /dev/video
名称,然后解析设备编号。
我的每个 video4linux 设备都会创建 2 个设备节点。例如,/dev/video0
和 /dev/video1
都与我的内部网络摄像头有关。当我插入第二个 USB 网络摄像头时,/dev/video2
和 /dev/video3
都会出现。但是,我只能使用每对中编号较小的设备进行视频捕获(即 /dev/video0
和 /dev/video2
)。
我用 udevadm monitor
看着我的设备到达,然后用 udevadm info --path=$PATH_FROM_UDEVADM_MONITOR --attribute-walk
检查了每个摄像头设备。用于视频捕获的设备有 ATTR{index}=="0"
.
也许您无需尝试打开 /dev/video1
,只需打开 /dev/video0
:
cam = cv2.CaptureVideo("/dev/video0")
其他答案中未探讨的一种可能性是使用 /sys/class/video4linux/video*/ 目录中的“名称”文件。
示例:
def get_camera(camera_name):
cam_num = None
for file in os.listdir("/sys/class/video4linux"):
real_file = os.path.realpath("/sys/class/video4linux/" + file + "/name")
with open(real_file, "rt") as name_file:
name = name_file.read().rstrip()
if camera_name in name:
cam_num = int(re.search("\d+$", file).group(0))
found = "FOUND!"
else:
found = " "
print("{} {} -> {}".format(found, file, name))
return cam_num
给出:
get_camera('HUE')
FOUND! video1 -> HUE HD Pro Camera: HUE HD Pro C
video0 -> HP HD Camera: HP HD Camera
创建视频捕获的正常方法是这样的:
cam = cv2.VideoCapture(n)
其中n对应/dev/video0
、dev/video1
但是因为我正在构建一个使用多个摄像头来处理不同事物的机器人,所以我需要确保它被分配给了正确的摄像头,我创建了 udev 规则来创建具有符号 link 的设备每当插入特定相机时,都会连接到正确的端口。
它们似乎在工作,因为当我查看 /dev
目录时,我可以看到 link:
/dev/front_cam -> video1
但是我不确定现在如何实际使用它。
我以为我可以直接从文件名打开它,就好像它是一个视频一样,但是 cam = cv2.VideoCapture('/dev/front_cam')
不起作用。
cv2.VideoCapture('/dev/video1')
它不会抛出错误,它会 return 一个 VideoCapture 对象,只是没有打开一个对象 (cam.isOpened()
returns False
)。
import re
import subprocess
import cv2
import os
device_re = re.compile("Bus\s+(?P<bus>\d+)\s+Device\s+(?P<device>\d+).+ID\s(?P<id>\w+:\w+)\s(?P<tag>.+)$", re.I)
df = subprocess.check_output("lsusb", shell=True)
for i in df.split('\n'):
if i:
info = device_re.match(i)
if info:
dinfo = info.groupdict()
if "Logitech, Inc. Webcam C270" in dinfo['tag']:
print "Camera found."
bus = dinfo['bus']
device = dinfo['device']
break
device_index = None
for file in os.listdir("/sys/class/video4linux"):
real_file = os.path.realpath("/sys/class/video4linux/" + file)
print real_file
print "/" + str(bus[-1]) + "-" + str(device[-1]) + "/"
if "/" + str(bus[-1]) + "-" + str(device[-1]) + "/" in real_file:
device_index = real_file[-1]
print "Hurray, device index is " + str(device_index)
camera = cv2.VideoCapture(int(device_index))
while True:
(grabbed, frame) = camera.read() # Grab the first frame
cv2.imshow("Camera", frame)
key = cv2.waitKey(1) & 0xFF
首先在USB 设备列表中搜索所需的字符串。获取总线和设备编号。
在 video4linux 目录下找到符号 link。从 realpath 中提取设备索引并将其传递给 VideoCapture 方法。
我找到了一个较短的解决方案,而不是建议的解决方案,感觉有点老套。
我只是看看符号link指向的位置,找到其中的整数,然后使用它。
import subprocess
cmd = "readlink -f /dev/CAMC"
process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
# output of form /dev/videoX
out = process.communicate()[0]
# parse for ints
nums = [int(x) for x in out if x.isdigit()]
cap = cv2.VideoCapture(nums[0])
如果您知道相机的型号,可以在/dev/v4l/by-id/...
中查找。我们正在使用 HDMI-USB 视频转换器,我们这样连接它:
#! /usr/bin/env python
import os
import re
import cv2
DEFAULT_CAMERA_NAME = '/dev/v4l/by-id/usb-AVerMedia_Technologies__Inc._Live_Gamer_Portable_2_Plus_5500114600612-video-index0'
device_num = 0
if os.path.exists(DEFAULT_CAMERA_NAME):
device_path = os.path.realpath(DEFAULT_CAMERA_NAME)
device_re = re.compile("\/dev\/video(\d+)")
info = device_re.match(device_path)
if info:
device_num = int(info.group(1))
print("Using default video capture device on /dev/video" + str(device_num))
cap = cv2.VideoCapture(device_num)
这遵循设备名称符号链接到 /dev/video
名称,然后解析设备编号。
我的每个 video4linux 设备都会创建 2 个设备节点。例如,/dev/video0
和 /dev/video1
都与我的内部网络摄像头有关。当我插入第二个 USB 网络摄像头时,/dev/video2
和 /dev/video3
都会出现。但是,我只能使用每对中编号较小的设备进行视频捕获(即 /dev/video0
和 /dev/video2
)。
我用 udevadm monitor
看着我的设备到达,然后用 udevadm info --path=$PATH_FROM_UDEVADM_MONITOR --attribute-walk
检查了每个摄像头设备。用于视频捕获的设备有 ATTR{index}=="0"
.
也许您无需尝试打开 /dev/video1
,只需打开 /dev/video0
:
cam = cv2.CaptureVideo("/dev/video0")
其他答案中未探讨的一种可能性是使用 /sys/class/video4linux/video*/ 目录中的“名称”文件。
示例:
def get_camera(camera_name):
cam_num = None
for file in os.listdir("/sys/class/video4linux"):
real_file = os.path.realpath("/sys/class/video4linux/" + file + "/name")
with open(real_file, "rt") as name_file:
name = name_file.read().rstrip()
if camera_name in name:
cam_num = int(re.search("\d+$", file).group(0))
found = "FOUND!"
else:
found = " "
print("{} {} -> {}".format(found, file, name))
return cam_num
给出:
get_camera('HUE')
FOUND! video1 -> HUE HD Pro Camera: HUE HD Pro C
video0 -> HP HD Camera: HP HD Camera