ii-pix/precompute_distance.py

71 lines
2.2 KiB
Python
Raw Normal View History

2021-01-25 23:16:46 +00:00
"""Precompute CIE2000 perceptual colour distance matrices.
The matrix of delta-E values is computed for all pairs of 24-bit RGB values,
and 4-bit Apple II target palette. This is a 256MB file that is mmapped at
runtime for efficient access.
"""
2021-01-25 22:28:00 +00:00
import argparse
2021-01-21 23:17:55 +00:00
import image
import palette as palette_py
2021-01-10 16:06:14 +00:00
import colour.difference
import numpy as np
COLOURS = 256
2021-01-10 20:10:32 +00:00
def rgb_to_lab(rgb: np.ndarray):
srgb = np.clip(
2021-01-21 23:17:55 +00:00
image.linear_to_srgb_array(rgb.astype(np.float32) / 255), 0.0,
2021-01-10 20:10:32 +00:00
1.0)
xyz = colour.sRGB_to_XYZ(srgb)
return colour.XYZ_to_Lab(xyz)
2021-01-25 22:28:00 +00:00
def all_lab_colours():
2021-01-10 16:06:14 +00:00
all_rgb = np.array(tuple(np.ndindex(COLOURS, COLOURS, COLOURS)),
dtype=np.uint8)
2021-01-25 22:28:00 +00:00
return rgb_to_lab(all_rgb)
def nearest_colours(palette, all_lab):
diffs = np.empty((COLOURS ** 3, 16), dtype=np.float32)
2021-01-10 16:06:14 +00:00
2021-01-25 22:28:00 +00:00
for i, palette_rgb in sorted(palette.RGB.items()):
print("...palette colour %d" % i)
2021-01-10 20:10:32 +00:00
palette_lab = rgb_to_lab(palette_rgb)
diffs[:, i] = colour.difference.delta_E_CIE2000(all_lab, palette_lab)
2021-01-10 16:06:14 +00:00
2021-01-10 20:10:32 +00:00
norm = np.max(diffs)
return (diffs / norm * 255).astype(np.uint8)
2021-01-10 16:06:14 +00:00
2021-01-21 23:17:55 +00:00
def main():
2021-01-25 22:28:00 +00:00
parser = argparse.ArgumentParser()
parser.add_argument('--palette', type=str, choices=list(
palette_py.PALETTES.keys()),
default=palette_py.DEFAULT_PALETTE,
help="Palette for which to compute distance matrix.")
parser.add_argument('--all', type=bool, default=False,
help="Whether to compute distances for all palettes")
args = parser.parse_args()
if args.all:
palette_names = list(palette_py.PALETTES.keys())
else:
palette_names = [args.palette]
print("Precomputing matrix of all 24-bit LAB colours")
all_lab = all_lab_colours()
for palette_name in palette_names:
print("Processing palette %s" % palette_name)
palette = palette_py.PALETTES[palette_name](load_distances=False)
n = nearest_colours(palette, all_lab)
out = np.memmap(filename=palette.DISTANCES_PATH, mode="w+",
dtype=np.uint8, shape=n.shape)
out[:] = n[:]
2021-01-21 23:17:55 +00:00
if __name__ == "__main__":
2021-01-25 22:28:00 +00:00
main()