Add support for euclidean distance in LAB space (though it doesn't

give good results and doesn't seem to be much faster anyway)

Clip RGB values before converting to LAB, to allow more easily
experimenting with not clipping the result of dithering, i.e. allowing
quantization error to take RGB values out of the 0..255 range.  This
may not improve quality but need to do more experiments.
This commit is contained in:
kris 2021-01-09 23:25:46 +00:00
parent db87ad2f9e
commit 9129e680f5

View File

@ -154,6 +154,14 @@ class CIE2000Distance(ColourDistance):
return colour.difference.delta_E_CIE2000(lab1, lab2)
class LABEuclideanDistance(ColourDistance):
"""Euclidean distance in LAB colour space."""
@staticmethod
def distance(lab1: np.ndarray, lab2: np.ndarray) -> float:
return np.sqrt(np.sum(np.power(lab1 - lab2, 2), axis=2))
# class CCIR601Distance(ColourDistance):
# @staticmethod
# def _to_luma(rgb: np.ndarray):
@ -308,8 +316,8 @@ class Dither:
if one_line:
yb = yt + 1
eb = et + 1
# print(xl, xr, el, er)
# print(image.shape, error.shape)
# TODO: compare without clipping here, i.e. allow RGB values to exceed
# 0-255 range
image[yt:yb, xl:xr, :] = np.clip(
image[yt:yb, xl:xr, :] + error[et:eb, el:er, :], 0, 255)
@ -403,7 +411,7 @@ def ideal_dither(screen: Screen, image: np.ndarray, image_lab: np.ndarray,
palette_choices_lab = np.array(list(LAB.values()))
for xx in range(x, min(max(x + lookahead, xr), screen.X_RES)):
input_pixel = np.copy(ideal_dither[y, xx, :])
input_pixel_lab = rgb_to_lab(input_pixel)
input_pixel_lab = rgb_to_lab(np.clip(input_pixel), 0, 255)
ideal_dither_lab[y, xx, :] = input_pixel_lab
output_pixel = screen.find_closest_color(input_pixel_lab,
palette_choices,
@ -454,7 +462,8 @@ def dither_lookahead(
# print("options=", options_rgb)
# print("rgb=",lah_image_rgb)
lah_image_lab = rgb_to_lab(lah_image_rgb[:, 0:lookahead, :])
lah_image_lab = rgb_to_lab(np.clip(lah_image_rgb[:, 0:lookahead, :], 0,
255))
error = differ.distance(lah_image_lab, options_lab)
# print(lah_image_lab)
# print("error=", error)
@ -478,7 +487,8 @@ def dither_image(
# Make sure lookahead region is updated from previously applied
# dithering
et, eb, el, er, yt, yb, xl, xr = dither.dither_bounds(screen, x, y)
image_lab[y, x:xr, :] = rgb_to_lab(image_rgb[y, x:xr, :])
image_lab[y, x:xr, :] = rgb_to_lab(
np.clip(image_rgb[y, x:xr, :], 0, 255))
# ideal_lab = ideal_dither(screen, image_rgb, image_lab, dither,
# differ, x, y, lookahead)
@ -516,6 +526,7 @@ def main():
dither = JarvisDither()
differ = CIE2000Distance()
# differ = LABEuclideanDistance()
# differ = CCIR601Distance()
output = dither_image(screen, image, dither, differ,