theaicompendium.com

K-Means Clustering for Image Classification Using OpenCV


In previous tutorials, we explored the k-means clustering algorithm as an unsupervised machine learning technique designed to group similar data points into distinct clusters, revealing underlying patterns in the data.

In this article, you will learn how to apply OpenCV’s k-means clustering algorithm specifically for image classification tasks.

Upon completing this tutorial, you will understand:

Let’s dive in!

Tutorial Overview

This tutorial consists of two primary sections:

  1. Understanding k-Means Clustering as an Unsupervised Learning Technique
  2. Applying k-Means Clustering to Image Classification

Understanding k-Means Clustering as an Unsupervised Learning Technique

The k-means clustering algorithm enables the automatic grouping of data into distinct categories (or clusters) where data points within each cluster exhibit similarity. This method is invaluable for uncovering patterns that might not be visible before clustering.

Previously, we applied k-means clustering to a simple two-dimensional dataset, allowing us to categorize data points based on distinct clusters. We also utilized this algorithm for color quantization, which reduces the number of colors present in an image.

In this tutorial, we will again harness the strengths of k-means clustering to classify images of handwritten digits from the OpenCV digits dataset without relying on ground truth labels.

Applying k-Means Clustering to Image Classification

We will start by loading the OpenCV digits image, dividing it into its corresponding sub-images that display handwritten digits from 0 to 9, and generating the associated ground truth labels. This setup will enable us to evaluate the k-means clustering algorithm’s performance later:

# Load the digits image and split it into sub-images
img, sub_imgs = split_images('Images/digits.png', 20)

# Create the ground truth labels
imgs, labels_true, _, _ = split_data(20, sub_imgs, 1.0)

The imgs array will contain 5,000 sub-images, organized in a row-wise format as flattened vectors of 400 pixels:

# Verify the shape of the 'imgs' array
print(imgs.shape)  # Output: (5000, 400)

We will configure the k-means algorithm, similar to how we approached color quantization, while inputting the imgs array and specifying the number of clusters K as 10 for the ten handwritten digits:

# Define termination criteria for the k-means algorithm
criteria = (TERM_CRITERIA_MAX_ITER + TERM_CRITERIA_EPS, 10, 1.0)

# Execute k-means clustering on the image data
compactness, clusters, centers = kmeans(data=imgs.astype(float32), K=10,
                                        bestLabels=None, criteria=criteria,
                                        attempts=10, flags=KMEANS_RANDOM_CENTERS)

The kmeans function returns a centers array, which contains a representative image for each cluster. The shape of the centers array will be 10 x 400, so we need to reshape it back into 20×20 pixel images for visualization:

# Reshape the array into 20x20 images
imgs_centers = centers.reshape(-1, 20, 20)

# Visualize the cluster centers
fig, ax = subplots(2, 5)

for i, center in zip(ax.flat, imgs_centers):
    i.imshow(center)

show()

The images generated by the k-means algorithm should resemble the handwritten digits present in the OpenCV digits dataset.

It’s worth noting that the order of the cluster centers may not match the digits 0 to 9, as the k-means algorithm does not account for numerical order when clustering. To remedy this, we will need to reorder the cluster labels:

# Define the cluster labels as determined
labels = array([2, 0, 7, 5, 1, 4, 6, 9, 3, 8])

labels_pred = zeros(labels_true.shape, dtype='int')

# Reorder cluster labels based on the established mapping
for i in range(10):
    mask = clusters.ravel() == i
    labels_pred[mask] = labels[i]

Now, we can compute the accuracy of our clustering by comparing the predicted labels to the ground truth labels:

# Calculate the accuracy of the algorithm
accuracy = (sum(labels_true == labels_pred) / labels_true.size) * 100

# Print the accuracy
print("Accuracy: {0:.2f}%".format(accuracy))

Improving Accuracy by Reducing Skew

Initially, the accuracy might be around 54.80%. To enhance this, we can introduce a function to adjust for any skew in the digit images, which involves applying affine transformations based on skew measurements acquired from image moments.

Conclusion

In this tutorial, you learned how to utilize OpenCV’s k-means clustering algorithm for classifying handwritten digits. You discovered:

Further Reading

To explore more about k-means clustering and image classification, consider the following resources:

Books:

Websites:

Feel free to let me know if you need more modifications or additional information!

Exit mobile version