Python 从接口名称而不是相机编号创建openCV VideoCapture
创建视频捕获的正常方法如下:Python 从接口名称而不是相机编号创建openCV VideoCapture,python,opencv,interface,udev,Python,Opencv,Interface,Udev,创建视频捕获的正常方法如下: cam=cv2.VideoCapture(n) 其中n对应于/dev/video0,dev/video1 但是因为我正在建造一个机器人,它使用多个摄像头来完成不同的任务,我需要确保它被分配到正确的摄像头,我创建了udev规则,创建了带有符号链接的设备,每当插入特定的摄像头时,都指向正确的端口 它们似乎在工作,因为当我查看/dev目录时,我可以看到以下链接: /dev/front\u cam->video1 但是我不知道现在该如何使用它 我想我可以从文件名打开它,就像
cam=cv2.VideoCapture(n)
其中n对应于/dev/video0
,dev/video1
但是因为我正在建造一个机器人,它使用多个摄像头来完成不同的任务,我需要确保它被分配到正确的摄像头,我创建了udev规则,创建了带有符号链接的设备,每当插入特定的摄像头时,都指向正确的端口
它们似乎在工作,因为当我查看/dev
目录时,我可以看到以下链接:
/dev/front\u cam->video1
但是我不知道现在该如何使用它
我想我可以从文件名打开它,就像它是一个视频一样,但是cam=cv2.VideoCapture('/dev/front\u-cam')
不起作用
cv2.VideoCapture('/dev/video1')
它不会抛出错误,它会返回一个VideoCapture对象,而不是一个打开的对象(cam.isOpened()
返回False
)。import re
导入子流程
进口cv2
导入操作系统
device_re=re.compile(“总线\s+(?P\d+)\s+设备\s+(?P\d+)。+ID\s(?P\w+:\w+)\s(?P+)$”,re.I)
df=子进程。检查_输出(“lsusb”,shell=True)
对于df.split('\n')中的i:
如果我:
信息=设备匹配(i)
如果信息:
dinfo=info.groupdict()
如果dinfo['tag']中的“Logitech,Inc.网络摄像头C270”:
打印“找到照相机”
总线=dinfo[“总线”]
设备=dinfo[“设备”]
打破
设备索引=无
对于os.listdir(“/sys/class/video4linux”)中的文件:
real_file=os.path.realpath(“/sys/class/video4linux/”+文件)
打印真实文件
打印“/”+str(总线[-1])+“-”+str(设备[-1])+“/”
如果real_文件中的“/”+str(总线[-1])+“-”+str(设备[-1])+“/”:
设备索引=实际文件[-1]
打印“万岁,设备索引为”+str(设备索引)
摄像机=cv2.视频捕获(int(设备索引))
尽管如此:
(抓取,帧)=相机。读取()#抓取第一帧
cv2.imshow(“摄像机”,帧)
key=cv2.waitKey(1)和0xFF
首先在USB设备列表中搜索所需字符串。获取总线和设备号
在video4linux目录下查找符号链接。从realpath中提取设备索引并将其传递给VideoCapture method。我找到了一个较短的解决方案,而不是建议的解决方案,这感觉有点粗糙 我只是看看符号链接点的位置,找到其中的整数,然后使用它
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监视器
观看了我的设备到达,然后用udevadm信息--path=$path\u FROM_udevadm\u监视器--attribute walk检查了每个摄像头设备。用于视频捕获的设备具有ATTR{index}==“0”
也许您不需要尝试打开/dev/video1
,而只需要打开/dev/video0
:
cam = cv2.CaptureVideo("/dev/video0")
其他答案中未探讨的一种可能性是使用/sys/class/video4linux/video*/目录中的“name”文件
例如:
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
能否从程序中读取符号链接,以便以编程方式获取字符串“/dev/video1”?如果是的话,你能从字符串(1)中提取数字并将其输入到你的openCV捕获对象吗?我对你的问题投了赞成票,我想这是个不错的问题。
get_camera('HUE')
FOUND! video1 -> HUE HD Pro Camera: HUE HD Pro C
video0 -> HP HD Camera: HP HD Camera