Skip to content

Instantly share code, notes, and snippets.

@FabianZweckinger
Last active June 3, 2023 19:25
Show Gist options
  • Save FabianZweckinger/fca5e4713adab29f7947f6f991313884 to your computer and use it in GitHub Desktop.
Save FabianZweckinger/fca5e4713adab29f7947f6f991313884 to your computer and use it in GitHub Desktop.
Python color quantization / reduction to a custom degree using CV2 library. The color palette gets chosen automatically, by the most used colors.
# Credits to Stackoverflow user u1234x1234
# Source: https://stackoverflow.com/questions/73666119/open-cv-python-quantize-to-a-given-color-palette
# The example was changed to automatically pick up the primary colors
import cv2
import numpy as np
image_path = 'input.png'
image_output_path = 'output.png'
quantize_count = 16 # How many colors will be left
def quantize_to_palette(image, palette):
x_query = image.reshape(-1, 3).astype(np.float32)
x_index = palette.astype(np.float32)
knn = cv2.ml.KNearest_create()
knn.train(x_index, cv2.ml.ROW_SAMPLE, np.arange(len(palette)))
ret, results, neighbours, dist = knn.findNearest(x_query, 1)
quantized_image = np.array([palette[idx] for idx in neighbours.astype(int)])
quantized_image = quantized_image.reshape(image.shape)
return quantized_image
def get_most_relevant_colors():
# Load image
img = cv2.imread(image_path)
# Convert image from BGR to RGB format
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Flatten image into a 2D array of pixels
pixels = img.reshape((-1, 3))
# Use NumPy's unique() and bincount() functions to count unique colors
unique_colors, counts = np.unique(pixels, axis=0, return_counts=True)
# Sort colors by count (most common first)
sorted_indices = np.argsort(-counts)
unique_colors = unique_colors[sorted_indices]
# Create an array of the most common colors in RGB format
rgb_colors = unique_colors[:quantize_count]
# Swap R and B colors
for i in range(len(rgb_colors)):
tmp = rgb_colors[i][0]
rgb_colors[i][0] = rgb_colors[i][2]
rgb_colors[i][2] = tmp
return rgb_colors
palette = get_most_relevant_colors()
# Quantize image with palette
input = cv2.imread(image_output_path)
output = quantize_to_palette(image=input, palette=np.array(palette))
cv2.imwrite(image_output_path, output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment