5 Best Ways to Convert a Colored Image to a Binary Image Using OpenCV and Python

πŸ’‘ Problem Formulation: In image processing, it’s often necessary to convert colored images into a binary format – where each pixel is either black or white. This is a fundamental step for various applications like document scanning and edge detection. Given a standard colored image, we aim to transform it into a binary (black and white) image using different thresholding techniques available in the OpenCV library with Python.

Method 1: Basic Thresholding

The most straightforward approach for converting a colored image to a binary one is basic thresholding. It involves comparing each pixel’s intensity with a predefined threshold value. In OpenCV, we can employ the cv2.threshold() function specifying the threshold value and the maximum value to assign to pixel values exceeding the threshold.

Here’s an example:

import cv2
# Read the image
image = cv2.imread('colored_image.jpg')
# Convert to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply basic thresholding
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
# Save the binary image
cv2.imwrite('binary_image.jpg', binary_image)

The output is a binary image file ‘binary_image.jpg’ where all pixels with a value greater than 127 are set to white, and the rest are set to black.

This code snippet reads a colored image and converts it to grayscale since thresholding requires a single channel image. The cv2.threshold() function is then used to perform the thresholding operation, resulting in the ‘binary_image.jpg’.

Method 2: Adaptive Thresholding

Adaptive thresholding is a method where the threshold value is determined for smaller regions, which allows for variable thresholds over different areas of the image. OpenCV’s cv2.adaptiveThreshold() is perfect for images with varying illumination.

Here’s an example:

import cv2
# Read the image
image = cv2.imread('colored_image.jpg')
# Convert to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply adaptive thresholding
binary_image = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                     cv2.THRESH_BINARY, 11, 2)
# Save the binary image
cv2.imwrite('binary_image_adaptive.jpg', binary_image)

The output is ‘binary_image_adaptive.jpg’ which consists of a binary representation of the original image, but with local thresholding for each 11×11 pixel neighborhood.

This snippet uses the cv2.adaptiveThreshold() with the threshold value calculated for each 11×11 region to account for different lighting conditions. The binary image is saved with thresholding adapted to the image’s local characteristics.

Method 3: Otsu’s Binarization

Otsu’s method is a global thresholding technique that chooses the threshold to minimize the intra-class variance of the black and white pixels. This automatic and robust threshold selection method is possible with OpenCV’s cv2.threshold() function by adding the cv2.THRESH_OTSU flag.

Here’s an example:

import cv2
# Read the image
image = cv2.imread('colored_image.jpg')
# Convert to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply Otsu's thresholding
_, binary_image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Save the binary image
cv2.imwrite('binary_image_otsu.jpg', binary_image)

The result is ‘binary_image_otsu.jpg’ where the optimal threshold is determined automatically.

In this method, Otsu’s algorithm is implemented by passing an extra flag to the cv2.threshold() function. It automatically computes the optimal threshold value for binarization of the grayscale image and applies it to produce the binary image.

Method 4: Color-based Segmentation

Color-based segmentation involves separating an image into regions based on color. When converting a colored image to binary, you can use this to focus the binarization on a specific color range using OpenCV’s inRange function.

Here’s an example:

import cv2
import numpy as np
# Read the image
image = cv2.imread('colored_image.jpg')
# Define the color range
lower_vals = np.array([30, 30, 30])
upper_vals = np.array([255, 255, 255])
# Segment out the color
binary_image = cv2.inRange(image, lower_vals, upper_vals)
# Save the binary image
cv2.imwrite('binary_image_segmented.jpg', binary_image)

The output is ‘binary_image_segmented.jpg’ with the specified color range converted to white and the rest to black.

Using the cv2.inRange() function, the code defines a range for the colors we want to extract. Pixels within this range are set to white, while others are set to black, resulting in a binary image focused on specific colors.

Bonus One-Liner Method 5: Thresholding with NumPy

In cases where a basic binary conversion is sufficient, NumPy can be used together with OpenCV to achieve a super concise one-liner. This approach uses NumPy’s ability to handle array operations conditioned on a particular threshold directly.

Here’s an example:

import cv2
import numpy as np
# Read the image and convert to grayscale
gray_image = cv2.cvtColor(cv2.imread('colored_image.jpg'), cv2.COLOR_BGR2GRAY)
# Perform binary conversion
binary_image = (gray_image > 127).astype(np.uint8) * 255
# Save the binary image
cv2.imwrite('binary_image_numpy.jpg', binary_image)

This outputs ‘binary_image_numpy.jpg’, a binary image created with a concise one-liner using NumPy.

The code takes advantage of NumPy’s fast array processing to threshold the grayscale image with a simple conditional expression. All pixel values above the threshold become white and the rest become black, simplifying the image conversion process into a single, readable line.

Summary/Discussion

  • Method 1: Basic Thresholding. Simple and fast. May not work well with variable lighting conditions or noisy images.
  • Method 2: Adaptive Thresholding. Handles different lighting conditions in the image. More computationally expensive than basic thresholding.
  • Method 3: Otsu’s Binarization. Automatically calculates the optimal threshold. Can perform poorly if the histogram is not bimodal.
  • Method 4: Color-based Segmentation. Effective for focusing on specific colors. Not suitable for general binarization where color is not a defining feature.
  • Method 5: Thresholding with NumPy. Extremely concise. Relies on basic thresholding so it shares similar strengths and weaknesses as Method 1.