Create openCV VideoCapture from interface name instead of camera numbers

后端 未结 5 883
眼角桃花
眼角桃花 2020-12-17 20:13

The normal way to create a videocapture is this:

cam = cv2.VideoCapture(n)

where n corresponds to the number of /dev/video0,

相关标签:
5条回答
  • 2020-12-17 20:31

    If you know the model of the camera, you can look it up in /dev/v4l/by-id/.... We are using an HDMI-USB video converter, and we connect to it like this:

    #! /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)
    

    This follows the device name symlink to the /dev/video name, then parses that for the device number.

    0 讨论(0)
  • 2020-12-17 20:37

    Each of my video4linux devices creates 2 device nodes. For example, /dev/video0 and /dev/video1 are both related to my internal webcam. When I plug in a second USB webcam, /dev/video2 and /dev/video3 both appear. However, I can only use the lower-numbered device of each pair for video capture (i.e. /dev/video0 and /dev/video2).

    I watched my device arrival with udevadm monitor, and then inspected each of the camera devices with udevadm info --path=$PATH_FROM_UDEVADM_MONITOR --attribute-walk. The devices which work for video capture have ATTR{index}=="0".

    Maybe instead of trying to open /dev/video1, you just need to open /dev/video0:

    cam = cv2.CaptureVideo("/dev/video0")
    
    0 讨论(0)
  • 2020-12-17 20:40

    A possibility that was not explored in the other answers is to use the "name" file in the /sys/class/video4linux/video*/ directories.

    Example :

    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
    

    Which gives :

    get_camera('HUE')
    FOUND! video1 -> HUE HD Pro Camera: HUE HD Pro C
        video0 -> HP HD Camera: HP HD Camera
    
    0 讨论(0)
  • 2020-12-17 20:50
    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
    

    First search for desired string in USB devices list. Get BUS and DEVICE number.

    Find symbolic link under video4linux directory. Extract device index from realpath and pass it to VideoCapture method.

    0 讨论(0)
  • 2020-12-17 20:53

    Instead of the suggested solution I found a shorter one, that feels a little bit hacky.

    I just look at where the symbolic link points, find the integer in it, and then use that.

    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])
    
    0 讨论(0)
提交回复
热议问题