Files
Vase-Matcher/colourIdentifier.py
2026-08-04 17:09:29 +05:30

112 lines
4.2 KiB
Python

import cv2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import webcolors
from scipy.spatial import KDTree
import webcolors
from scipy.spatial import KDTree
def get_closest_color_name(rgb_tuple):
"""
Finds the nearest human-readable color name for any given RGB tuple.
Compatible with both newer and older versions of the 'webcolors' library.
"""
# 1. Fetch color names and RGB mapping based on webcolors version
try:
# Modern webcolors syntax
color_names = webcolors.names("css3")
rgb_values = [webcolors.name_to_rgb(name, spec="css3") for name in color_names]
except AttributeError:
# Legacy webcolors fallback (v1.11 or older)
css3_db = getattr(webcolors, "CSS3_HEX_TO_NAMES", webcolors.css3_hex_to_names)
color_names = list(css3_db.values())
rgb_values = [webcolors.hex_to_rgb(hex_code) for hex_code in css3_db.keys()]
# 2. Query nearest neighbor using KDTree
kdt_db = KDTree(rgb_values)
_, index = kdt_db.query(rgb_tuple)
return color_names[index]
def visualize_named_color_segmentation(image_path, num_colors=5, output_file="named_segmented_result.png"):
"""
Segments an image by dominant colors, identifies human-readable color names,
creates individual region masks, and plots a visual report.
"""
# 1. Load image and convert to RGB
image = cv2.imread(image_path)
if image is None:
raise FileNotFoundError(f"Could not load image at path: {image_path}")
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 2. Reshape for K-Means
pixels = image_rgb.reshape((-1, 3))
# 3. Apply K-Means Clustering
kmeans = KMeans(n_clusters=num_colors, n_init=10, random_state=42)
labels = kmeans.fit_predict(pixels)
colors = kmeans.cluster_centers_.astype(int)
# Calculate pixel counts and percentages
counts = np.bincount(labels)
total_pixels = len(pixels)
sorted_indices = np.argsort(counts)[::-1] # Sort by area size (largest first)
# 4. Create the full segmented image (Quantized Image)
segmented_pixels = colors[labels]
segmented_image = segmented_pixels.reshape(image_rgb.shape)
# 5. Build Subplot Grid for Visualization
cols = 3
rows = int(np.ceil((num_colors + 2) / cols))
plt.figure(figsize=(16, 4.5 * rows))
# Display Original Image
plt.subplot(rows, cols, 1)
plt.imshow(image_rgb)
plt.title("Original Image", fontsize=12, fontweight='bold')
plt.axis("off")
# Display Full Color-Segmented Image
plt.subplot(rows, cols, 2)
plt.imshow(segmented_image)
plt.title(f"Segmented Image ({num_colors} Colors)", fontsize=12, fontweight='bold')
plt.axis("off")
# Display Individual Color Region Masks with Color Names
labels_2d = labels.reshape(image_rgb.shape[:2])
for i, idx in enumerate(sorted_indices):
cluster_color = tuple(colors[idx])
percentage = (counts[idx] / total_pixels) * 100
hex_code = f"#{cluster_color[0]:02x}{cluster_color[1]:02x}{cluster_color[2]:02x}"
# Get human-readable color name
color_name = get_closest_color_name(cluster_color).capitalize()
# Create an isolated view for this specific color region
region_mask = (labels_2d == idx)
isolated_region = np.zeros_like(image_rgb)
isolated_region[region_mask] = image_rgb[region_mask]
# Plot individual segmented mask
plt.subplot(rows, cols, i + 3)
plt.imshow(isolated_region)
plt.title(
f"Region {i+1}: {color_name} ({percentage:.2f}%)\nRGB: {cluster_color} | HEX: {hex_code}",
fontsize=11, fontweight='bold'
)
plt.axis("off")
plt.tight_layout()
plt.savefig(output_file, dpi=300, bbox_inches='tight')
print(f"Segmented output successfully saved to '{output_file}'")
plt.show()
# --- Example Usage ---
if __name__ == "__main__":
IMAGE_FILE = "/media/suman/Backup_of_extra_/Sasi/Flowers_images/imgR_nobg.png" # Replace with your image file path
# Run segmentation with color name detection
visualize_named_color_segmentation(IMAGE_FILE, num_colors=4, output_file="named_segmented_regions.png")