2

I set the resolution to full hd (width=1920, height=1080) on my c920 webcam and used the cv2.CAP_DSHOW API which supports this camera.

However, the fps was very low. The next thing i tried is to autodetect the API by simply writing

camera = cv2.VideoCapture(0, cv2.CAP_ANY)

Now I get very high fps but it is not a 16:9 format anymore, it has some black side bars on the left and right side of the image like in this post: OpenCV capturing imagem with black side bars

Is there are way to:

  1. Find out which API has been autodetected?
  2. Find out which format is being used?
  3. Can I change the format afterwards manually without losing much of the gained performance?

Or do you have a better idea how to handle this problem?

Printing camera says it's still full hd:

(grabbed, frame0) = camera.read()
print(len(frame0[0])) # = 1920
print(len(frame0)) # = 1080
Azrion
  • 117
  • 2
  • 14

1 Answers1

2

Multiple Devices (Webcams) Connected? A brief question before I answer do you have another webcam connected? I.e. an integrated laptop webcam, additionally to the c920? At the bottom of this answer you find a function to check all available devices that openCV recognizes.

Answer 1:
Yes there is getBackendName() to check what openCV automatically detected. See the snippet below (Link to the docs):

video = cv2.VideoCapture(1, cv2.CAP_ANY)
print(video.getBackendName())

Answer 2 & 3:
You can also check the current format with .get() and insert the property of interest. See again the snippet below (as well as the docs). In a similar fashin you can set the format with the .set() method (see also below)

video = cv2.VideoCapture(1, cv2.CAP_ANY)
print(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Regardless of the auto selected API you can change the format again with the .set method
video.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
video.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

Check Available Devices
Here would be a quick function that gives you the indicies of all available devices

def get_available_devices():
    index = 0
    arr = []
    while True:
        cap = cv2.VideoCapture(index)
        if not cap.read()[0]:
            break
        else:
            arr.append(index)
        cap.release()
        index += 1
    return arr
Björn
  • 1,610
  • 2
  • 17
  • 37
  • The autodetected backend is CAP_MSMF (this is the one that shows black sidebars on the left and right side of the image). When I print out the current format with .get() it is still full hd (1920x1080), which doesn't make sense because the black sidebars are still visible. – Azrion Apr 09 '20 at 14:20
  • However, when i use the backend CAP_DSHOW it is also in full hd but the black sidebars disappear (this is what i want). But the problem with CAP_DSHOW is that it is using the 'YUY2' encoder which causes low fps. On the other hand, CAP_MSMF is using the 'NV12' encoder and has high fps. I tried setting NV12 encoder in CAP_DSHOW but it just doesn't support it Any ideas? – Azrion Apr 09 '20 at 14:20
  • 1
    Hi first of all thank you for awarding the bounty and accepting my answer. I think this would qualify as a new question. However in this [link](https://www.pyimagesearch.com/2017/02/06/faster-video-file-fps-with-cv2-videocapture-and-opencv/) it is suggested to work with threads to improve FPS of webcam captures – Björn Apr 09 '20 at 22:09
  • 1
    I also found this [link](https://answers.opencv.org/question/6805/how-to-get-mjpeg-compression-format-from-webcam/) suggests "set the Fourcc also in the original stream from the webcam, because if you don't set it to MJPG, it assumes RGB and so at HD res the fps is 5fps.". I guess its worth trying
    `video.set(cv2.CAP_PROP_FOURCC,cv2.VideoWriter_fourcc(*'MJPG'))`
    – Björn Apr 09 '20 at 22:12
  • 1
    your last comment actually solve the low fps issue!! thank you very much for your help – Azrion Apr 10 '20 at 19:51