For the color search on Pattern Design(a great platform for vector designs), I recently created a color search query powered by Elasticsearch. Try it, it works great.
In the schema mapping the average color is stored as an integer
averageColor { properties { red { type 'integer' } green { type 'integer' } blue { type 'integer' } } }
For the query, we use a range query to get the images with the matching colors (plus/minus some tolerance). In order to get the best matches first, the scoring is (for simplicity) based on a Manhattan distance of the result color compared to the search color. The colorRange function ensures that the queried values lie within the rgb range. (the query string is constructed in php, thus the syntax)
{ size: 100, query : { function_score: { filter : { and : [ { "range" : { "averageColor.red" : { "gte": '.colorRange($red - $tolerance).', "lte": '.colorRange($red + $tolerance).' } }}, {"range" : { "averageColor.green" : { "gte" :'.colorRange($green - $tolerance).', "lte" : '.colorRange($green + $tolerance).' } }}, {"range" : { "averageColor.blue" : { "gte" :'.colorRange($blue - $tolerance).', "lte" : '.colorRange($blue + $tolerance).' } }} ]}, script_score: { "params": { "red": '.$red.', "green": '.$green.', "blue": '.$blue.' }, script: "-(abs(doc[\'averageColor.red\'].value - (double)red)+abs(doc[\'averageColor.green\'].value - green)+abs(doc[\'averageColor.blue\'].value - blue))" } } } }
Hi,
I have question about it.
What value do you store in $tolerance and can you please provide example of colorRange() ?
Hi Serg,
we’re using 100 for tolerance (which is a pretty wide range, but is not a problem because the result is sorted by match)
colorRange is actually only pseudocode in this context – it basically just clamps the value between 0 and 255. The implementation of colorRange looks like this:
Nice.
Thank you!
Hello there,
How do you calculate a single rgb color from a whole image?
By calculating the average of all colors (i.e. pixels) in the image. This is quite primitive and will not work well on images with many different colors (resulting in a muddy brown), but works well on images which have a overall tone or dominant color. The average is also what a human would see if she looked at it from far away.