La façon normale de créer une capture vidéo est la suivante:

cam = cv2.VideoCapture(n)

Où n correspond au nombre de /dev/video0, dev/video1

Mais parce que je construis un robot qui utilise plusieurs caméras pour différentes choses, je devais m'assurer qu'il était affecté à la bonne caméra, j'ai créé des règles udev qui ont créé des appareils avec des liens symboliques vers le port approprié chaque fois qu'une caméra spécifique était branché.

Ils semblent fonctionner parce que quand je regarde dans le répertoire /dev je peux voir le lien:

/dev/front_cam -> video1

Cependant, je ne sais pas vraiment comment utiliser cela maintenant.

Je pensais que je pouvais juste l'ouvrir à partir du nom de fichier, comme s'il s'agissait d'une vidéo, mais cam = cv2.VideoCapture('/dev/front_cam') ne fonctionne pas.

cv2.VideoCapture('/dev/video1') non plus

Il ne génère pas d'erreur, il renvoie un objet VideoCapture, mais pas un objet ouvert (cam.isOpened() renvoie False).

6
KenArrari 6 mars 2016 à 03:47

4 réponses

Meilleure réponse
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

Recherchez d'abord la chaîne souhaitée dans la liste des périphériques USB. Obtenez le numéro de BUS et APPAREIL.

Trouvez un lien symbolique sous le répertoire video4linux. Extrayez l'index de périphérique de realpath et passez-le à la méthode VideoCapture.

1
mertyildiran 6 mars 2016 à 01:56

Chacun de mes appareils video4linux crée 2 nœuds d'appareils. Par exemple, /dev/video0 et /dev/video1 sont tous deux liés à ma webcam interne. Lorsque je branche une deuxième webcam USB, /dev/video2 et /dev/video3 apparaissent tous les deux. Cependant, je ne peux utiliser que l'appareil de numéro inférieur de chaque paire pour la capture vidéo (c'est-à-dire /dev/video0 et /dev/video2).

J'ai regardé l'arrivée de mon appareil avec udevadm monitor, puis j'ai inspecté chacun des appareils photo avec udevadm info --path=$PATH_FROM_UDEVADM_MONITOR --attribute-walk. Les appareils qui fonctionnent pour la capture vidéo ont ATTR{index}=="0".

Peut-être qu'au lieu d'essayer d'ouvrir /dev/video1, il vous suffit d'ouvrir /dev/video0:

cam = cv2.CaptureVideo("/dev/video0")
2
bontragersw 31 oct. 2019 à 20:00

Au lieu de la solution suggérée, j'en ai trouvé une plus courte, qui semble un peu hacky.

Je regarde simplement où le lien symbolique pointe, je trouve l'entier qu'il contient, puis je l'utilise.

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])
1
KenArrari 7 mars 2016 à 04:08

Si vous connaissez le modèle de la caméra, vous pouvez le rechercher dans /dev/v4l/by-id/.... Nous utilisons un convertisseur vidéo HDMI-USB, et nous nous y connectons comme ceci:

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

Cela suit le lien symbolique du nom du périphérique vers le nom /dev/video, puis analyse celui du numéro de périphérique.

1
arprice 21 août 2019 à 17:08