Reputation: 237
Im writing a program that analyzes a picture and returns the most prominent color. Its simple to get the most frequently occurring color but I've found that very often this color is a dark black/gray/brown or a white and not the "color" you would associate with the image. So I'd like to get the top 5 colors and compare them based on some metric to determine which color is most "Vibrant/Colorful" and return that color.
Saturation wont work in this case because a saturated black will be ranked above a lighter pink and Brightness/Luminance wont work because a white will be ranked about a darker red. Im want to know what metric I can use to judge this. I recognize this is kind of an obtuse question but I know of other programs that do similar things so I assume there must be some way to calculate "Vibrancy/Colorfulness". It doesn't need to be perfect just work most of the time
For what its worth I'm working in javascript but the actual code is not the issue, I just need the equation I can use and then I can implement it
After trying several different formulas I had the most success with the following
let colorfulness = ((max+ min) * (max-min))/max
where max & min are the highest and lowest RGB values, respectively. This page has a more detailed explanation of the formula itself.
This will return a value between 0 and 255 with 0 being least colorful and 255 being most. From running this on a bunch of different colors, I found that for my application any value above 50 was colorful enough, thought you can adjust this.
My final code is as follows
function getColorFromImage(image) {
//gets the three most commonly occuring, distinct colors in an image as RGB values, in order of their frequency
let palette = getPaletteFromImage(image, 3)
for (let color of palette){
var colorfulness = 0
//(0,0,0) will return NAN if used in the formula, if (0,0,0) leave colorfulness as its default 0
if (color != [0,0,0]){
//get min & max values
let min = Math.min(color)
let max = Math.max(color)
//calculate colorfulness of color
colorfulness = ((max+ min) * (max-min))/max
}
//compare color's colorfulness against a threshold to determine if color is "colorful" enough
//ive found 50 is a good threshold but adjust as needed
if (colorfulness >= 50.0){
return color
}
}
//if none of the colors are deemed to be sufficiently colorful, just return the most common
return palette[0]
}
Upvotes: 2
Views: 1475
Reputation: 11643
Vibrance is not an attribuite of a single color like saturation, it instead considers the image globally. Increasing the vibrance of an image (as usually found in many photo editing software) means increasing the saturation of the less saturated colors to match the already saturated ones.
Upvotes: 1
Reputation: 32898
There is no common way to define "vibrancy" of a color. Thus, you can try combining multiple metrics such as "saturation", "brightness", and "luminance". The lower the overall metric is, the better. The following is an example in pseudocode.
// Compare metrics to "ideal"
var deltaSat = Saturation(thisColor) - idealSat;
var deltaBright = Brightness(thisColor) - idealBrightness;
var deltaLum = Luminance(thisColor) - idealLum;
// Calculate overall distance from ideal; the lower
// the better.
var dist = sqrt((deltaSat*deltaSat) +
(deltaBright*deltaBright) +
(deltaLum*deltaLum))
(If your issue is merely that you're having trouble calculating a metric for a given color, see my page on color topics for programmers.)
If your criteria for "vibrancy" are complex enough, you should consider using machine learning techniques such as classification algorithms. In machine learning in general:
Machine learning is quite complex, however, so you should try the simpler method given earlier in this answer.
Upvotes: 1
Reputation: 237
After trying several different formulas I had the most success with the following
let colorfulness = ((max+ min) * (max-min))/max
where max & min are the highest and lowest RGB values, respectively. This page has a more detailed explanation of the formula itself.
This will return a value between 0 and 255 with 0 being least colorful and 255 being most. From running this on a bunch of different colors, I found that for my application any value above 50 was colorful enough, thought you can adjust this.
My final code is as follows
function getColorFromImage(image) {
//gets the three most commonly occuring, distinct colors in an image as RGB values, in order of their frequency
let palette = getPaletteFromImage(image, 3)
for (let color of palette){
var colorfulness = 0
//(0,0,0) will return NAN if used in the formula, if (0,0,0) leave colorfulness as its default 0
if (color != [0,0,0]){
//get min & max values
let min = Math.min(color)
let max = Math.max(color)
//calculate colorfulness of color
colorfulness = ((max+ min) * (max-min))/max
}
//compare color's colorfulness against a threshold to determine if color is "colorful" enough
//ive found 50 is a good threshold but adjust as needed
if (colorfulness >= 50.0){
return color
}
}
//if none of the colors are deemed to be sufficiently colorful, just return the most common
return palette[0]
}
Upvotes: 1