go-colorful icon indicating copy to clipboard operation
go-colorful copied to clipboard

YIQ colorspace and YIQ distance

Open makew0rld opened this issue 4 years ago • 3 comments

The YIQ colorspace can be useful for quickly measuring the perceived difference between two colors. This is what odiff uses to measure the difference between images. The README references this paper.

The YIQ conversion and special YIQ distance algorithm have already been implemented in Go here, but should be compared with the paper just in case.

makew0rld avatar Mar 08 '21 19:03 makew0rld

@makew0rld thanks for noting this! It might make my work in https://github.com/mccutchen/palettor/pull/8 (replacing RGB euclidean distance with a better perceptual distance measure) faster.

That code does $k$-means clustering by repeatedly iterating over the pixels in the same image. Each time it visits a pixel, it measures the distance between that pixel and a number of "centroids" being optimized.

As I understand it, there are two frequent arithmetic operations:

  1. Translating RGB-internal colorful.Colors into HCL.
  2. Finding the squared euclidean HCL distance between colors.

Implementing a (colorful.Color).Yiq() function may speed up the first process, since converting the RGBA colorful.Color into $(Y, I, Q)$ is faster than the conversion into $(H, C, L)$.

The second operation remains essentially the same speed: whether in HCL or YIQ, I'm taking a euclidean distance in 3D space.

It seems to me the bigger performance improvement would come from actually storing HCL and YIQ values. colorful.Color may become an interface – a translation-rich superset of color.Color – that exports different struct implementations, like the color package itself does.

That might all seem out-of-scope for this package, but I figured I'd write it up in case that's of interest!

Also, for future readers: see https://github.com/dmtrKovalenko/odiff/pull/81 for an updated link to the YIQ paper referenced here.

lukasschwab avatar Mar 17 '23 02:03 lukasschwab

It seems to me the bigger performance improvement would come from actually storing HCL and YIQ values.

Storing HCL representations made a significant impact. My benchmark results are here – compare 'Main branch' (using colorful.Color) to 'Feaure branch' (using colorful.Color to build internal hcl structs): https://github.com/lukasschwab/palettor/pull/2

lukasschwab avatar Mar 17 '23 16:03 lukasschwab

Thanks for the updated paper link. I do think colorful.Color becoming an interface is out of scope and too big a change, but thanks for the suggestion.

makew0rld avatar Mar 18 '23 16:03 makew0rld