Skip to Content

How do I filter out color in OpenCV?

OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. It has C++, Python, Java and MATLAB interfaces and supports Windows, Linux, Mac OS, iOS and Android. OpenCV was designed for computational efficiency and with a strong focus on real-time applications. It is used for all sorts of image and video analysis, like facial recognition and detection, license plate reading, photo editing, advanced robotic vision, optical character recognition, and a whole lot more.

One common task in image processing and computer vision is to filter out certain colors in an image. This allows you to isolate a specific color or color range for further analysis, segmentation, tracking etc. In OpenCV, this can be achieved using various color space conversion and thresholding techniques. In this post, we will see how to filter out a particular color or range of colors in OpenCV using Python.

Color Spaces

The first step is to understand how OpenCV represents color images. OpenCV reads images into NumPy arrays in the BGR (Blue, Green, Red) format by default. But OpenCV provides conversions to other color spaces like HSV and Lab which are more intuitive for color based filtering.

BGR Color Space

The default BGR color space separates color channels into Blue, Green and Red. The channel values range from 0 to 255. Filtering out a color directly in BGR space is difficult because the 3 channels are correlated. Instead we need to convert to a more intuitive color space like HSV or Lab.

HSV Color Space

The HSV color space represents color using 3 values – Hue, Saturation and Value. This separates color (Hue and Saturation) from brightness (Value). Hue represents the dominant color which ranges from 0 to 179. Saturation describes the intensity of color and ranges from 0 to 255. Value works like image brightness and ranges from 0 to 255. HSV makes it very easy to filter out colors based on the Hue.

LAB Color Space

The Lab color space uses 3 channels – Lightness, green-red axis (a) and blue-yellow axis (b). The Lightness channel ranges from 0 to 100. The a channel represents green to red with negative values indicating green and positive values indicating red/magenta. The b channel represents blue to yellow with negative values indicating blue and positive values indicating yellow. Lab makes it easy to threshold colors based on the a and b channels.

Converting Color Spaces

Since HSV and Lab make color based filtering easier, we need to convert the OpenCV BGR image to these color spaces. This can be done with the cv2.cvtColor() function in OpenCV.

To convert from BGR to HSV:

import cv2

# Load BGR image
img = cv2.imread('image.jpg') 

# Convert to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

To convert from BGR to Lab:

import cv2

# Load BGR image 
img = cv2.imread('image.jpg')

# Convert to Lab 
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

This gives us the HSV and Lab representations of the image which are better for color based filtering.

Filtering in HSV

In HSV, we can filter out a color range based on the Hue and Saturation ranges. Here are some examples:

Filter Red Color

# lower and upper bounds for red color
lower_red = np.array([0,50,50]) 
upper_red = np.array([10,255,255])

# Filter red color from HSV image
mask = cv2.inRange(hsv, lower_red, upper_red)
result = cv2.bitwise_and(img, img, mask=mask)

Here we define lower and upper HSV bounds for red color. The Hue range is 0-10 for red. We keep full Saturation and Value range. We apply the threshold mask to filter out red portions of the image.

Filter Green Color

# lower and upper bounds for green color 
lower_green = np.array([50, 50, 50])
upper_green = np.array([70, 255, 255]) 

# Filter green color from HSV image
mask = cv2.inRange(hsv, lower_green, upper_green)
result = cv2.bitwise_and(img, img, mask=mask)

For green, the Hue range is 50-70. We threshold the HSV image based on this to filter out green color.

Filter Blue Color

# lower and upper bounds for blue color
lower_blue = np.array([100, 50, 50])
upper_blue = np.array([130, 255, 255])

# Filter blue color from HSV image  
mask = cv2.inRange(hsv, lower_blue, upper_blue)
result = cv2.bitwise_and(img, img, mask=mask)

Here the Hue range for blue is 100-130. We apply thresholding to filter out the blue regions.

By tuning the Hue and Saturation ranges, you can isolate any color from the HSV image.

Filtering in Lab

In Lab color space, we can threshold based on the a and b channels to isolate a color range. Some examples:

Filter Red Color

# lower and upper bounds for red color 
lower_red = np.array([70, 50, 50])
upper_red = np.array([255, 255, 255])

# Filter red regions
mask = cv2.inRange(lab, lower_red, upper_red)
result = cv2.bitwise_and(img, img, mask=mask)

Red color has positive a channel values. So we threshold from 70 to 255 to isolate red regions.

Filter Blue Color

# lower and upper bounds for blue color
lower_blue = np.array([0, 0, 50])  
upper_blue = np.array([70, 255, 255])

# Filter blue regions
mask = cv2.inRange(lab, lower_blue, upper_blue)
result = cv2.bitwise_and(img, img, mask=mask) 

Blue color has negative b channel values. So we threshold from 0 to 70 to isolate blue regions.

Filter Green Color

# lower and upper bounds for green color
lower_green = np.array([0, 0, 50])
upper_green = np.array([255, 255, 255]) 

# Filter green regions
mask = cv2.inRange(lab, lower_green, upper_green)
result = cv2.bitwise_and(img, img, mask=mask)

Green has low a and b channel values. So we keep them low and threshold to isolate greens.

By tuning the a and b channel thresholds, you can filter any color ranges from the Lab image.

Contour Detection

After applying color thresholding, we can find contours in the mask image to isolate objects of that color. This allows you to detect shapes, segment objects etc of a particular color from the image.

To find contours from the mask image, we can use the cv2.findContours() function:

import cv2

# get mask image 
mask = cv2.inRange(hsv, lower_red, upper_red)

# find contours 
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

# draw contours on image
result = cv2.drawContours(img, contours, -1, (0,255,0), 3)

This finds contours from the red mask image and draws them on the original image. You can then analyze these contours for shape detection, object tracking etc.

Color Based Segmentation

By thresholding colors and finding contours, you can achieve image segmentation based on color. Segmentation allows separating objects in an image for analysis and recognition.

Here is an example to segment blue colored objects:

import cv2
import numpy as np

# load image
img = cv2.imread('image.jpg')

# convert BGR to Lab 
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

# threshold blue color
lower_blue = np.array([0, 0, 50])
upper_blue = np.array([70, 255, 255])
mask = cv2.inRange(lab, lower_blue, upper_blue)

# find contours 
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

# initialize output image 
output = np.zeros(img.shape, dtype='uint8') 

# draw blue contours on output
cv2.drawContours(output, contours, -1, (255, 0, 0), 3)

# show output 
cv2.imshow('Output', output)
cv2.waitKey(0)

This thresholds the Lab image to isolate blue regions, finds contours and draws them on the output, achieving blue object segmentation.

Tracking a Color Object

You can use color based filtering to track objects of a particular color in a video. To track a blue object:

import cv2
import numpy as np

# capture video
cap = cv2.VideoCapture('video.mp4') 

while True:
    # read each frame 
    ret, frame = cap.read()  

    # convert to LAB
    lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)

    # threshold blue
    lower_blue = np.array([0,0,50])
    upper_blue = np.array([70,255,255])
    mask = cv2.inRange(lab, lower_blue, upper_blue)
    
    # find and draw contours
    contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    cv2.drawContours(frame, contours, -1, (0,0,255), 2)

    cv2.imshow('Tracking', frame)
    
    if cv2.waitKey(1) == ord('q'):
        break
        
cap.release()
cv2.destroyAllWindows()

This thresholds each frame to isolate blues, finds contours and draws them to track blue objects in the video.

Conclusion

To summarize, here are the main steps to filter out a color in OpenCV:

  1. Load image as BGR
  2. Convert to HSV or Lab color space
  3. Define lower and upper threshold bounds for color
  4. Threshold HSV or Lab image
  5. Apply bitwise AND on mask to extract color
  6. (Optional) Find contours in mask to isolate objects

The key is converting to an intuitive color space like HSV or Lab first. This makes it easy to define color ranges and threshold images. By tuning the threshold values, you can isolate any color. Advanced techniques like contour detection and segmentation can help in analyzing images based on color.

OpenCV provides all the building blocks needed for efficient color filtering and detection in images and videos. With its extensive library and simple Python interface, implementing real-time color based tracking and analytics becomes very easy.