Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - How to sort a list of colors based on a color's "distance" from a source color in 3D (r, g, b) space?

Here are the basic steps to an app I'm writing in Python:

  1. Generate a list of random colors
  2. Create a mapping of each of those colors, indexed by that color's distance to a "source color" in 3D (r, g, b) space. (For instance, orange (255, 150, 0) is closer to red(255, 0, 0) than dark blue (0, 0, 100). By now, I have a list of tuples of the format (distance, color).
  3. Sort that list of tuples based on the distances I had calculated (from lowest, to highest).
  4. Retrieve a list of the sorted colors

Here is my function, and I get the following error: TypeError: 'int' object has no attribute '_getitem_' on the line sorted_by_dist = sorted(colorMap, key=lambda tup: tup[0])

# Sorts a list of colors according to distance from the source color
def sort_colors(colors, source):
    colorMap = ()
    sortedColors = list()
    for i in range(len(colors)):
        dist = dist_3d(colors[i], source)
        colorMap = colorMap + (dist, colors[i])

    sorted_by_dist = sorted(colorMap, key=lambda tup: tup[0])

    for (d, c) in sorted_by_dist:
        sortedColors.append(c)

    return sortedColors

Assuming my dist_3d() function is correct and returns an integer value (it is, and does), what am I doing wrong? I don't understand.

like image 612
Brian Avatar asked Jan 05 '13 04:01

Brian


People also ask

How do you sort things by color?

When organizing by color, look to the rainbow. Walker recommends this method as you sort: "Start with white, cream, pink, red, orange, yellow, green, blue, indigo, violet, brown, gray, and black," she says. Gold and silver can be tricky, so she suggests moving them around to see what looks best to you.

What is RGB sort?

RGB sorting The most trivial way in which we can sort colours is by directing sort its RGB values. Python has a very naive way of doing this: it sorts the first component, then the second and finally the third one.

What is sort color?

Colour sorters are used for the food processing industry, such as coffee, nuts, and oil crops. The goal is the separation of items that are discoloured, toxic (such as ergot), not as ripe as required, or still with hull after dehulling such as sunflower seeds..


2 Answers

You are building your colorMap as a big single dimensional tuple, with the first index being an int. So your lambda is being passed an int and then you try to index into it.

You probably want a list of tuples:

colorMap = []
...
    dist = dist_3d(colors[i], source)
    colorMap.append((dist, colors[i]))

In terms of an approach to sorting colors, I have actually used a kdtree module for this, loaded up with all my RGB tuples. Then I can ask it for N closest colors to a given color tuple:

from kdtree import KDTree

colors = [(10,10,10),(250,50,5),(100,50,20)]
query_color = (175, 25, 50)

tree = KDTree.construct_from_data(data)
# query the 2 closest colors
nearest = tree.query(query_point=query_color, t=2)
like image 197
jdi Avatar answered Sep 20 '22 23:09

jdi


The error is because tup is an int. __getitem__ is the name of the [] operator.

But, it looks like all your function is doing is sorting a list of colors, based on distance from some reference color. And, you already have dist_3d implemented. Given that it works, then sorting your colors is much simpler. Sort them in place:

colors.sort(key=lambda color: dist_3d(color, reference_color))

or as a new list:

sorted_colors = sorted(unsorted_colors, key=lambda color: dist_3d(color, reference_color))

No need for all that tuple-building and looping and stuff in your function, as I can tell.

like image 24
Phil Frost Avatar answered Sep 18 '22 23:09

Phil Frost