gka / chroma.js

JavaScript library for all kinds of color manipulations
https://gka.github.io/chroma.js/
Other
10.19k stars 546 forks source link

Group similar Colors #216

Open Jrfidellis opened 5 years ago

Jrfidellis commented 5 years ago

Hi!

I'm doing a website that should analyze pictures of a Rubik's cube and extract its colors (to reach a solution).

In order to do that I am taking the average color of every square of the cube (6 faces x 9 squares per face, resulting in 54 colors).

My problem was: how to find the color of each one of the faces? I tryed some stuff and got this:

The function receives all the colors (54 in my case) and the size of each color group (9 in my case, the amount of extracted colors that belong to a cube face).

It will return 6 colors (54 divided by 9), representing each face of the cube.

groupCloseColors(colorsRgb: IRGB[], groupSize: number) {
    const resultColors: chroma.Color[] = []
    let colors = colorsRgb.map(({ r, g, b}) => chroma.rgb(r, g, b))

    new Array(colors.length / groupSize)
      .fill(groupSize)
      .forEach(() => {
        const sample = colors.splice(0, 1)[0]
        const colorsCloserToSample = colors
          .map(color => ({
            color,
            distance: chroma.distance(color, sample)
          }))
          .sort((a, b) => a.distance - b.distance)
          .slice(0, groupSize - 1)
          .map(({ color }) => color)

        colors = colors.filter((c) => colorsCloserToSample.every(cs => cs !== c))
        const result = chroma.average([...colorsCloserToSample, sample])
        resultColors.push(result)
      })

    return resultColors
  }

Example of input and output: image

I think that maybe this would be a good addition to chroma.js, what you guys think?