Last active
June 3, 2023 19:25
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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