5 Best Ways to Compute and Plot 2D Histograms of an Image in OpenCV Python

πŸ’‘ Problem Formulation: We often need to analyze the intensity distribution or color profiles in images for various computer vision tasks. A 2D histogram is a graphical representation of this distribution where two features are considered simultaneously. This article will guide you through methods on how to compute and visualize 2D histograms (such as color histograms) using OpenCV and Python, considering an input image and desiring a plotted histogram as the output.

Method 1: Using Matplotlib and OpenCV

This method involves using the calcHist function in OpenCV to compute the histogram and then plotting it with the popular Matplotlib library’s imshow() function for 2D graphical representation. It gives us powerful insights into color distribution and intensity with a customizable color map.

Here’s an example:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Load image
image = cv2.imread('path_to_image.jpg')
# Convert to RGB
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# Compute 2D histogram
hist = cv2.calcHist([image], [0, 1], None, [256, 256], [0, 256, 0, 256])

# Plot the histogram
plt.imshow(hist, interpolation = 'nearest')
plt.title('2D Color Histogram')
plt.xlabel('Red Channel')
plt.ylabel('Green Channel')
plt.show()

The output will be a 2D plot representing the intensities of the red and green channels.

By converting the image into RGB format and calculating a 2D histogram for the Red and Green channels, this approach gives a visual mapping of how often different combinations of red and green pixel values occur. The imshow() function then elegantly displays this information.

Method 2: Normalized 2D Histogram

Normalization helps in comparing histograms across different sized images. OpenCV allows for easy histogram normalization using the normalize() function. This method relates the pixel counts for each bin of the histogram to the total number of pixels.

Here’s an example:

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread('path_to_image.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
hist = cv2.calcHist([image], [0, 1], None, [256, 256], [0, 256, 0, 256])

# Normalize the histogram
cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)

plt.imshow(hist.astype(np.uint8), interpolation = 'nearest')
plt.show()

The output is a normalized 2D histogram plot which can be directly compared with other histograms.

This snippet computes the histogram with calcHist() and then normalizes the values so that the highest point is at the value 255, improving the contrast of the histogram. This is useful when comparing histograms of different images.

Method 3: Back Projection of Histogram

Back projection is the process of mapping histogram bins back onto the original image, essentially highlighting the parts of the image that conform to the histogram features. This can be instrumental in object tracking and image segmentation tasks within OpenCV.

Here’s an example:

import cv2
import numpy as np

image = cv2.imread('path_to_image.jpg')
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# Compute the 2D histogram
hist = cv2.calcHist([hsv_image], [0, 1], None, [180, 256], [0, 180, 0, 256])
cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)

# Back Projection
back_project = cv2.calcBackProject([hsv_image], [0, 1], hist, [0, 180, 0, 256], 1)

# Display back projection
cv2.imshow("BackProjection", back_project)
cv2.waitKey(0)

The output is an image where the pixels from the original correspond in brightness to their frequency in the histogram.

The code calculates the histogram in the HSV space for better color distinction, normalizes it, and then applies the back projection, resulting in areas of the original image that match the histogram appearing brighter than the rest.

Method 4: 2D Histogram with Masking

Applying a mask allows you to focus the histogram computation on a specific area of interest within the image. This can be particularly useful when you wish to analyze the color distribution of a particular object within a scene without interference from background colors.

Here’s an example:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Load image and create mask
image = cv2.imread('path_to_image.jpg')
mask = np.zeros(image.shape[:2], dtype="uint8")
cv2.rectangle(mask, (startX, startY), (endX, endY), 255, -1)

# Compute 2D histogram with mask
hist_mask = cv2.calcHist([image], [0, 1], mask, [256, 256], [0, 256, 0, 256])
plt.imshow(hist_mask, interpolation = 'nearest')
plt.show()

The output will be a histogram plot focusing on the histogram values within the specified rectangle.

This code applies a mask over the desired portion of the image using a simple rectangle, but any binary mask can be used. The histogram is then computed only for the masked region, allowing detailed analysis of that section’s colors.

Bonus One-Liner Method 5: OpenCV’s plot() Function

For a quick and simple visualization of a 2D histogram, OpenCV provides a plot() function via the cv2.imshow() method. This approach is best when a fast and easy display of the histogram data is needed without any additional customization.

Here’s an example:

import cv2
# Assuming 'hist' is a precomputed 2D histogram
cv2.imshow('2D Histogram', hist)
cv2.waitKey(0)

The output is a window showing the 2D histogram directly.

Here, the hist variable assumes that a 2D histogram has been already computed using any of the previous methods. This code snippet simply uses the OpenCV’s image display function to show the histogram.

Summary/Discussion

  • Method 1: Matplotlib and OpenCV. Strengths: Provides a customizable plotting environment. Weaknesses: Requires additional library installation.
  • Method 2: Normalized 2D Histogram. Strengths: Offers comparison between different image histograms. Weaknesses: May obscure some detail by focusing on relative rather than absolute frequencies.
  • Method 3: Back Projection. Strengths: Useful for object tracking and image segmentation. Weaknesses: More complex and may require further tuning of histogram parameters.
  • Method 4: Masking. Strengths: Allows analysis of specific image regions. Weaknesses: Extra step of mask creation required.
  • Bonus Method 5: OpenCV’s plot(). Strengths: Quick and easy visualization. Weaknesses: Less customization and control over the output display.