I have a 100×100 image:
<img id="my-face" src="/my-face.jpg" />
I get all of its pixels and I calculate the average RGB of that image:
let img = document.getElementById('my-face') let avgRgbOfImg = getAverageRGb(img)
I also have a reference RGB of a different color:
let refRgb = [255, 244, 50] // yellow
I know now want to add a filter to the image, so that the
avgRgbOfImg gets pretty close to my
addFilter(refRgb).to(img) let newAvgRgb = getAverageRGb(img) // should be pretty close to `refRgb` (yellow)
In simpler terms, I have an image and I want to use canvas (or p5.js) to add a color filter to it so that it’s
avgRgbOfImg gets pretty close to that color.
Is there some canvas/p5 sets of methods to achieve this ?
Interesting approach using RGB to get the average colour.
In the past I’ve answered a vaguely similar question but doing basic image search based on average colour. Instead of RGB colour space I’ve used Lab* colour space which is a perceptual colour space. I simply used this implementation of the
You might get slightly better results, but based on the demo you posted hopefully not extremely dissimilar. Does it justify the complexity: not sure.
Speaking of complexity you could go all the way to deep neural networks. Doing a quick search, Progressive Color Transfer with Dense Semantic Correspondences along with a related implementation. Maybe in a roundabout way that PyTorch model could be trained and exported to Tensorflow.js (
PyTorch -> ONNX -> TensorFlow -> TensorFlow.js) and used directly or integrated with ml5.js similar to the StyleTransfer model.
Maybe it could produce interesting results, but it will surely be a complex approach.
If you already know the average RGB colour of an image and you’re after an approximation/similar look how about “faking it” by simply tinting the image via
tint(). You could even control the amount of tint using the 4th(alpha) argument:
// apply 50% of refRgb tint(refRgb, refRgb, refRgb, 128); image(theImageYouWanTinted, 0, 0);
Sure the output will be a mixture of the source image and refRgb, but it’s super easy to test if visually it achieves what you’re after.
You could then expand and try other things, for example:
- use the grayscale version of the image you want to tint instead of the rgb one
- based on the image content’s perhaps a single colour channel would have more dominant / appealing features (e.g. instead of true grayscale use either red, green or blue channel as grayscale)
- further filter the source image to try and extract relevant information (e.g. smooth the image a bit with a median filter, try a low pass filter, etc.)
It’s hard to gauge how precise and complex things need to be: I’d simply go for
tint() first. (If you need to “freeze” the tinted result to pixels remember you could always get a “snapshot” of what’s been drawn using
get() and more complex things could be achieved using a p5.Graphics layer (see