Pulling full resolution from a webcam with OpenCV (Windows)

7 Comments

OpenCV while being the most popular tool for a lot of machine vision applications it relies on a third party and some poorly maintained code. Capturing MJPEG compressed video from a UVC USB camera was always the case and it did not work or worked with some issues. This situation is especially bad for Windows OS.

Currently Python 3.8.4 pip has these versions of OpenCV available to be installed directly: 3.4.8.29, 3.4.9.31, 3.4.9.33, 3.4.10.35, 4.1.2.30, 4.2.0.32, 4.2.0.34, 4.3.0.36

Each version can be installed (and replaced) with ease by typing so it’s fairly easy to test versions that are in pip package manager repository:

pip install opencv-python==4.3.0.36

Classic / minimalistic way to capture images is like this:

import cv2

camera = cv2.VideoCapture(0)

while (1):
    retval, im = camera.read()
    cv2.imshow("image", im)

    k = cv2.waitKey(1) & 0xff
    if k == 27:
        break

camera.release()
cv2.destroyAllWindows()

Unfortunately, sometimes it needs some more parameters to actually capture MJPEG stream. For older OpenCV (last tested 3.4.2.x) versions there was a solution to add cv2.CAP_PROP_FOURCC property set and the whole code to have 1920×1080 at 30fps stream looked like this:

import cv2

camera = cv2.VideoCapture(0)

codec = 0x47504A4D  # MJPG
camera.set(cv2.CAP_PROP_FPS, 30.0)
camera.set(cv2.CAP_PROP_FOURCC, codec)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

while (1):
    retval, im = camera.read(0)
    cv2.imshow("image", im)

    k = cv2.waitKey(1) & 0xff
    if k == 27:
        break

camera.release()
cv2.destroyAllWindows()

Once the last OpenCV version available in the pip repository was updated and this workaround stopped working. Since 3.4.10.35 OpenCV version was rolled out it stopped working at all and frames could not be captured anymore. One more property had to be added cv2.CAP_DSHOW so now code looks like this:

import cv2

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

codec = 0x47504A4D  # MJPG
camera.set(cv2.CAP_PROP_FPS, 30.0)
camera.set(cv2.CAP_PROP_FOURCC, codec)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

while (1):
    retval, im = camera.read()
    cv2.imshow("image", im)

    k = cv2.waitKey(1) & 0xff
    if k == 27:
        break

camera.release()
cv2.destroyAllWindows()

One problem remains. Frames are not being captured at 30 frames per second rate. So one more fix and we have 1080p@30fps with MJPEG compression stream in our code.

import cv2

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

camera.set(cv2.CAP_PROP_FPS, 30.0)
camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('m','j','p','g'))
camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M','J','P','G'))
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

while (1):
    retval, im = camera.read()
    cv2.imshow("image", im)

    k = cv2.waitKey(1) & 0xff
    if k == 27:
        break

camera.release()
cv2.destroyAllWindows()

This solution may not work for all operating systems, versions, and cameras. Most intense tests were performed with C1 family cameras.

Comments ( 7 )

  1. Rob
    I had been using code similar to your top example (with Python 3.9.0 and Opencv 4.5.1 on Windows 8.1) which worked fine with the built-in 640x480 webcam on my laptop. But it wouldn't work with a HD USB camera. I used your code, and now it works fine - many thanks! Two strange things - first the parameter for VideoCapture is still "0" - the same as I was using for the webcam in the original code. Usually, you use "1" or "2" for additional cameras. Secondly, running the new code mostly accesses the USB HD camera - but just occasionally it accesses the *original* webcam, even though there has been no change in the code.
    • saulius
      Hi Rob, glad it was useful! Maybe cameras enumerate randomly? Also cap_dshow.cpp in opencv code (windows camera capture part) is ancient and requires total rewrite.
  2. kcwcc
    This seems to be highly camera dependant. It worked GREAT for my internal webcam, but not for my external webcams. Might be something to do with openCV, hardware, win10...who knows? Internal webcam (720p, 30FPS) Method 1: Not DIRECT SHOW Method 2: Direct show with FPS 6.12 seconds to access and set up camera 2.53 seconds to access and set up camera 1280 x 720 resolution 1280 x 720 resolution FPS:26 FPS:29 Logitech C920 (1080p, 30FPS) Method 1: Not DIRECT SHOW Method 2: Direct show with FPS 80.50 seconds to access and set up camera 1.58 seconds to access and set up camera 1920 x 1080 resolution 1920 x 1080 resolution FPS:25 FPS:14 Method 1: Not DIRECT SHOW Method 2: Direct show with FPS 81.95 seconds to access and set up camera 1.55 seconds to access and set up camera 1280 x 720 resolution 1280 x 720 resolution FPS:26 FPS:14 Logitech C270 (720p, 30FPS (doubt that)) Method 1: Not DIRECT SHOW Method 2: Direct show with FPS 0.28 seconds to access and set up camera 1.18 seconds to access and set up camera 1280 x 720 resolution 1280 x 720 resolution FPS:18 FPS:12 Cheap Chinese (1080p, 30FPS) Method 1: Not DIRECT SHOW Method 2: Direct show with FPS 51.26 seconds to access and set up camera 2.30 seconds to access and set up camera 1920 x 1080 resolution 1920 x 1080 resolution FPS:26 FPS:19 Method 1: Not DIRECT SHOW Method 2: Direct show with FPS 51.97 seconds to access and set up camera 2.28 seconds to access and set up camera 1280 x 720 resolution 1280 x 720 resolution FPS:26 FPS:19 It's pretty annoying actually. Thanks for posting though!
  3. kcwcc
    Damn. It reformatted my comment. Sorry about that
    • saulius
      It's me who should apologize. Looks like WP does not like formatted text in comments.
  4. kcwcc
    This appears to be very camera dependent. Worked great for my internal webcam but not for external webcams. No idea why but frame rate takes a BIG hit. Tried 4 cameras and different results for all of them at both 1080p and 720p.
    • saulius
      Unfortunately you are correct. OpenCV Camera capture backend has many underlying implementations. Camera capture code in Windows screams for complete rewrite.

Leave a reply

Your email address will not be published.