How to specify exact camera by id to prevent two usb cameras from being switched around macos

what i need is the ability for two usb cameras to not get switched around so i would have camera A pointing in one direction then camera B pointing in a different direction and within opencv even after a reboot or unpluging the cameras each of those cameras remains associated to the proper frame

but when trying to do this using indexes
ex
cap = cv2.VideoCapture(1)
sometimes it will access my built in webcam or the usb camera attached to it or a 3rd camera if thats attached, ive heard that on linux you can specify which webcam you want with
cap = cv2.VideoCapture("/dev/video0")
but there does not seam to be an analogue to this on mac

im on an m1 air ventura 13.2.1

and here is my example code

import cv2
import os
cwd = os.getcwd()
cap = cv2.VideoCapture(1)

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
ret, img = cap.read()
path = cwd + "/calibrationimages/"
print(path)
count = 0
while True:
    name = path + str(count)+".jpg"
    ret, img = cap.read()
    cv2.imshow("img", img)


    if cv2.waitKey(20) & 0xFF == ord('c'):
        cv2.imwrite(name, img)
        cv2.imshow("img", img)
        count += 1
        if cv2.waitKey(0) & 0xFF == ord('q'):

            break

I don’t know on MacOS, but on Linux you have alternative path for the camera in /dev/v4l/by-id/, where the file name contains the unique camera ID.

Maybe you have a similar thing in MacOS.

hi i have tried that but for one i cant seam to figure out what the correct name for the camera would be and the tools to list out whats there don’t say much about a /dev/ folder

You can run this code to specify the right USB Camera.

import cv2

cap0 = cv2.VideoCapture()
cap1 = cv2.VideoCapture()

cap0.open(1)
cap1.open(1)
while(True):
    ret,frame0 = cap0.read()
    ret, frame = cap1.read()

    cv2.imshow("0",frame0)
    # or 
    # cv2.imshow("1",frame)
    if(cv2.waitKey(1) & 0xFF == ord('q')):
        break
    

I guess there is a circle queue saving cameras. When you plug a USB Camera, OS will push the built-in Camera to the end of this queue firstly. Then, we have two elements(one is USBCam, the other is built-in Cam) at index 1. cap.open() or cv2.VideoCapture(1) will be initialized cyclically. You can verify this by creating another .py call .open then you will find the image displayed by our first .py change.

In practice, it’s a very tricky question. Because we can’t promise our program will read the right image!

that code is wrong. you can’t open the same index twice. the rest of your post also makes little to no sense. if that is due to a language barrier, you should use machine translation instead.

hello
after a lot of research i discovered a partial fix however it is quite janky. basically i use run from subprocess to call ffmpeg with this command

ffmpeg -f avfoundation -list_devices true -i “”

in the command line which then returns the name and opencv camera index for all cameras, then you simply find the index corresponding to your cameras name and use that with opencv. i dont know how this will function with multiple of the same camera tho as i only have one webcam to test with, there might be a similar function that can return a unique id for each camera using ffmpeg but im unaware if one exists
heres my code

import cv2
import os
from subprocess import PIPE, run

camera_name = "Arducam OV9281 USB Camera"
command = ['ffmpeg','-f', 'avfoundation','-list_devices','true','-i','""']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
cam_id = 0

for item in result.stderr.splitlines():
    if camera_name in item:
        cam_id = int(item.split("[")[2].split(']')[0])
print("cam id", cam_id)

cap = cv2.VideoCapture(cam_id)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
ret_val , cap_for_exposure = cap.read()

in future i hope to find a way that can just use which usb port the camera is connected too