Controlling Contrast and Brightness of Video Stream in OpenCV and Python

10,973

I found the solution using the numpy.clip() method and @fmw42 provided a solution using the cv2.normalize() method. I like the cv2.normalize() solution slightly better because it normalizes the pixel values to 0-255 rather than clip them at 0 or 255. Both solutions are provided here.

The cv2.normalize() solution:

  • Brightness - shift the alpha and beta values the same amount. Alpha can be negative and beta can be higher than 255. (If alpha >= 255, then the picture is white and if beta <= 0, then the picure is black.
  • Contrast - Widen or shorten the gap between alpha and beta.

Here is the code:

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    cv2.normalize(frame, frame, 0, 255, cv2.NORM_MINMAX)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

The numpy.clip() solution:

This helped me solve the problem: How to fast change image brightness with python + OpenCV?. I need to:

  1. Convert Red-Green Blue (RGB) to Hue-Saturation-Value (HSV) first (“Value” is the same as “Brightness”)
  2. “Slice” the Numpy array to the Value portion of the Numpy array and adjust brightness and contrast on that slice
  3. Convert back from HSV to RGB.

Here is the working solution. Vary the contrast and brightness values. numpy.clip() ensures that all the pixel values remain between 0 and 255 in each on the channels (R, G, and B).

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    contrast = 1.25
    brightness = 50
    frame[:,:,2] = np.clip(contrast * frame[:,:,2] + brightness, 0, 255)
    frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
Share:
10,973
slalomchip
Author by

slalomchip

Updated on June 05, 2022

Comments

  • slalomchip
    slalomchip almost 2 years

    I’m using OpenCV3 and Python 3.7 to capture a live video stream from my webcam and I want to control the brightness and contrast. I cannot control the camera settings using OpenCV's cap.set(cv2.CAP_PROP_BRIGHTNESS, float) and cap.set(cv2.CAP_PROP_BRIGHTNESS, int) commands so I want to apply the contrast and brightness after each frame is read. The Numpy array of each captured image is (480, 640, 3). The following code properly displays the video stream without any attempt to change the brightness or contrast.

    import numpy as np
    import cv2
    
    cap = cv2.VideoCapture(0)    
    while(True):
        # Capture frame-by-frame
        ret, frame = cap.read()
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    # When everything done, release the capture
    cap.release()
    cv2.destroyAllWindows()
    

    I get a washed-out video stream when I use Numpy’s clip() method to control the contrast and brightness, even when I set contrast = 1.0 (no change to contrast) and brightness = 0 (no change to brightness). Here is my attempt to control contrast and brightness.

    import numpy as np
    import cv2
    
    cap = cv2.VideoCapture(0)
    while(True):
        # Capture frame-by-frame
        ret, frame = cap.read()
        contrast = 1.0
        brightness = 0
        frame = np.clip(contrast * frame + brightness, 0, 255)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    # When everything done, release the capture
    cap.release()
    cv2.destroyAllWindows()
    

    How can I control the contrast and brightness of a video stream using OpenCV?

  • fmw42
    fmw42 about 4 years
    You can change brightness and contrast with cv2.normalize()
  • slalomchip
    slalomchip about 4 years
    @fmw42 - I added your solution to my answer. I like cv2.normalize() better than numpy.clip() because cv2.normalize() doesn't clip the edges. Thanks!
  • fmw42
    fmw42 about 4 years
    You can use alpha and beta in cv2.normalize with values outside the 0 to 255 range if you want more contrast or brightness. For example cv2.normalize(hist, None, alpha=0, beta=1.5*255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)