from Hacker News

I tested services to extract colors from image

by kiru_io on 5/17/23, 11:23 AM with 14 comments

  • by csense on 5/19/23, 4:57 AM

    This is not too surprising.

    The most obvious way to implement something like this is to just histogram the pixels and sort by most popular, it's like literally 4 lines of Python:

        # Find the n most popular colors in the array of pixels
        def most_popular_colors(pixels, n):
            count = {}
            for i in range(len(pixels)):
                count[pixels[i]] = count.get(pixels[i], 0)+1
            return sorted(count.items(), key=lambda kv : kv[1], reverse=True)[:n]
    
    This works (for some definition of "works"), but it doesn't do what users expect. They will probably complain a lot about the results.

    Any image that's a photo, or uses a gradient, or has ever been JPEG or MPEG compressed, is going to have a ton of fine variations in its colors. All the pixels of "that shade of green" aren't going to be exactly #123499, some of them are going to be #133499 or #123498 or something. A simple histogram like the above code will tally all those distinct colors separately.

    So you can get a most-popular list containing multiple very, very similar shades that are technically distinct integers. And you can have a color that "should" be on the most-popular list but isn't, because it's a bunch of very subtly different shades, none of which has a high enough count to crack the list.

    Which means to get the behavior the users expect, a simple histogram simply won't do. You need additional logic to "bucket" similar colors together for the counting part, and then show a "representative" of the most popular buckets for the final output.

    How are the buckets defined? How are the representatives selected? There are probably a dozen different reasonable implementation choices you could make. Different choices will all give slightly different (or even very different) outputs.

    I would actually be very surprised to find two independently written programs would give the same output for this problem, and I would suspect they're not actually independent (i.e. they both used the same software or both found the same textbook or RFC or whatever that suggests very specific implementation choices.)

  • by Lt_Riza_Hawkeye on 5/21/23, 2:50 AM

    gpick is also a great piece of software on linux - unfortunately they got threatened by pantone or something and had to remove the good color names like "midnight moss", "mineral green", and "bombay". Everything now pulls up as "light green", "faded green", or "bluegrey". However, the rest of the functionality is the best you could ask for.

    http://0x0.st/Hqoj.png

  • by fwlr on 5/22/23, 1:47 AM

    Another major factor that goes into “the main colors in an image”, but doesn’t get picked up by these services, is the “visual importance” of different colors. For example, in the image used in the post, you probably want the color of the bird, the color of mountains, the color of trees, and the color of the sky at a minimum. But getting information about what elements are important is hard. Perhaps you can get some of the way with those new segmenting AIs.
  • by hoyd on 5/21/23, 11:04 AM

    Nice to see others need for this, and also experiencing differences. To add one more, i tried it on my hobby web app https://apps.hoyd.net/hexcolors/uploads/hex-background-promp...
  • by bravura on 5/21/23, 4:36 AM

    I recently spent about two hours trying to write a script to automatically color grade an input image according to the palette of a target image. The results were unsatisfying and I was surprised that achieving this task was much trickier than I initially anticipated.
  • by rf15 on 5/21/23, 8:56 AM

    It is interesting how every color in this is secretly watermarked with the name of the site - why would you want to do that?