Skip to content

Instantly share code, notes, and snippets.

@Anthony-Hoo
Created December 19, 2023 06:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Anthony-Hoo/b1630f320f990444d485ca0de6a52c10 to your computer and use it in GitHub Desktop.
Save Anthony-Hoo/b1630f320f990444d485ca0de6a52c10 to your computer and use it in GitHub Desktop.
Converts image input to CIE xy chromaticity coordinates with original pixel colour
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import time
from colour.plotting import *
def plot_xy_coordinates_with_color(xy_and_rgb_np, output_png_path):
start_time = time.time()
xy = xy_and_rgb_np[:, :2]
RGB = xy_and_rgb_np[:, 2:5]
if RGB.max() > 1:
RGB = RGB / 255.0
plot_chromaticity_diagram_CIE1931(show = False, show_diagram_colours = False)
ax = plt.gca()
ax.set_title('CIE 1931 Chromaticity Diagram')
ax.scatter(xy[:, 0], xy[:, 1], color=RGB, s=0.01, edgecolors=None, linewidths=0)
plt.savefig(output_png_path, format='png', dpi=500)
plt.close()
print('Drawing Chromaticity Diagram spent: {:.2f} seconds'.format(time.time() - start_time))
def image_to_cie_xy_and_rgb(image_path):
start_time = time.time()
with Image.open(image_path) as img:
img = img.convert('RGB')
image_data = np.array(img, dtype=np.float16)
pixels = image_data.reshape(-1, 3)
sum_xyz = np.sum(pixels, axis=1, keepdims=True)
xy_coordinates = np.divide(pixels[:, :2], sum_xyz, out=np.zeros_like(pixels[:, :2], dtype=np.float16), where=sum_xyz!=0)
xy_and_rgb = np.hstack([xy_coordinates, pixels])
print('Computing XYZ and RGB spent: {:.2f} seconds'.format(time.time() - start_time))
return xy_and_rgb
if __name__ == "__main__":
'''
The Python script converts image RGB data to CIE xy chromaticity coordinates and RGB values
using PIL and NumPy (function image_to_cie_xy_and_rgb).
It then visualizes these coordinates on the CIE 1931 Chromaticity Diagram
with Matplotlib and colour.plotting, coloring each point according to
its RGB value (function plot_xy_coordinates_with_color).
The development focused on optimizing data processing and visualization,
utilizing vectorized operations for efficiency,
ensuring accurate color representation, and producing visual output.
'''
image_path = './test.jpg'
xy_and_rgb = image_to_cie_xy_and_rgb(image_path)
output_png_path = 'cie_diagram.png'
plot_xy_coordinates_with_color(xy_and_rgb, output_png_path)
@Anthony-Hoo
Copy link
Author

The following is a set of image samples, for input images:
test

After processing, you can get:
cie_diagram

@Dawars
Copy link

Dawars commented Mar 12, 2024

I had to change the plotting code to put it on the same figure in Jupyter notebook

fig, ax = plt.subplots()
    
  ax.set_title('CIE 1931 Chromaticity Diagram')
  ax.scatter(xy[:, 0], xy[:, 1], color=RGB, s=0.01, edgecolors=None, linewidths=0)
  
  plot_chromaticity_diagram_CIE1931(show=False, show_diagram_colours=False, figure=fig, axes=ax)
  
#     plt.savefig(output_png_path, format='png', dpi=100)
  fig.show()
  plt.close(fig)

@Anthony-Hoo
Copy link
Author

@Dawars There are significant logic issues in this code version, causing the graph it generates to inaccurately represent the pixel distribution in the photo within the CIE color space.

My friend @Rachel030219 pointed out these issues and provided the fixed code. You can view the version of the code he modified here. If you want to learn more, please visit his blog (please note that the blog is in Chinese).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment