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:
- Load image as BGR
- Convert to HSV or Lab color space
- Define lower and upper threshold bounds for color
- Threshold HSV or Lab image
- Apply bitwise AND on mask to extract color
- (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.