Extract the "overall colors" of an image to apply another?
15 views (last 30 days)
Show older comments
I've been meaning to show my students a way to "borrow" the color palette of an image to apply to another?
Take the Mona Lisa, for example. It has its own "tones" and "mood". Suppose there was a way to load that image into Matlab and extract its "most vital" color characteristic? And then be able to "apply" this "personality" to any other existing image? I know, it's a crazy idea and I've been thinking what could possibly be the "linking mechanism" between the two images or between any two sets of images, for that matter, that would make this possible? Perhaps the "Brightness" levels? To me, it's clearly a problem of "mapping tones" between imiages but I have no idea where to start. But one thing is sure, the students would immediately understand the idea and, from a pedagogical point of view, it would go a long way towards building an "abstract" view of "image processing" which is what the class is about.
0 Comments
Accepted Answer
DGM
on 14 Jun 2023
Edited: DGM
on 15 Jun 2023
The paper that @Image Analyst linked is probably the ideal, but nobody posted a MATLAB implementation yet. I think there are a couple image recoloring examples on the FEX, but if I recall, they're based on semantic segmentation and don't use a reference image as the color source.
MIMT has two somewhat-applicable tools, neither of which are very good for photographic images, but both of which are better than using an unsorted color table.
MIMT imrecolor() uses histogram matching to transfer color information from one image to another. This is accomplished by sorting the pixels into a specified number of bins by brightness and then performing histogram matching on the hue and chroma/saturation data within each of those bins. The result is a brightness-correlated color distribution match between the images. This tool tends to produce patchy results with photographic content, but for simple cases it's sometimes passable. It was originally intended for use with abstract images.
ref = imread('flowers.png');
inpict = imread('shoes.png');
outpict = imrecolor(ref,inpict,'colormodel','hsly');
imshow(outpict)
Compare that to a simple histogram matching in RGB using imhistmatch():
While imhistmatch() does do a better job of reproducing the color distribution, it does so with no regard to preserving the brightness or contrast of the original image.
MIMT also has a simpler way that's similar to the example you gave. MIMT im2ct() was written as a response to this FEX submission, and all it does is create a color table of specified length using the "dominant" colors of an image. The CT is sorted and optionally linearized in a specified color space.
Bear in mind that this is a simple tool, and it should be expected that there are many configurations of images and options which will yield completely garbage results. Often what people call the "dominant colors" are not representative of the dominant fraction of the image, and there's no reason to expect that there is a monotonic and visually pleasing trajectory between them. It's usually best to use only a small number of sample points (nbreaks) to avoid banding.
Instead of applying this color table directly using ind2rgb(), we reduce the image to its corresponding brightness component and quantize that. In this manner, we're maintaining some brightness relationship. In MIMT, the tool to use would be gray2pcolor().
ref = imread('flowers.png');
inpict = imread('shoes.png');
CT = im2ct(ref,'ncolors',256,'nbreaks',5,'uniform',true, ...
'cspace','ypbpr','fullrange',true,'minsat',0.15);
outpict = gray2pcolor(inpict,CT,imclassrange(class(inpict)),'default');
% display both the CT and the recolored image
subplot(8,1,1)
image(rot90(ctflop(CT)))
subplot(8,1,2:8)
imshow(outpict)
2 Comments
DGM
on 15 Jun 2023
I'm not the color sci guy around here, but even as much as I've tinkered with it, I don't have a good solution to the "thematic colors" extraction problem.
For the purposes of color transfer, I'd think that a method used for extraction would have a dual that could be used to apply them to the working image. The problem that always stumped me was that once we get a good color table by finding characteristic groups in some color space, how do we arbitrarily reshape the color distribution of the working image to match without causing local inversions or banding? The problem is that the grouping of colors in LAB or RGB tends to be only weakly associated with the representative colors of each particular object in an image, and they tend to overlap anyway. Moving the group dominated by one object will often create bands and blobs elsewhere where once-smoothly graduated shadows or highlights move away from their spatial neighbors, simply due to where the group boundaries were chosen in the color space.
The Grundland paper (if I recall) addresses this, but that was quite a bit over my head.
More Answers (2)
Richard Burnside
on 14 Jun 2023
Edited: Richard Burnside
on 14 Jun 2023
The imread command will return the indexed image and the 256x3 colormap of the image:
[X,cmap] = imread('corn.tif');
You can work with that colormap to apply it to another image using the colormap command.
4 Comments
Richard Burnside
on 14 Jun 2023
The answer supplied below by Image Analyst seems to have that process worked out. Pretty amazing results.
Image Analyst
on 14 Jun 2023
The best algorithm I've seen for transferring the color gamut is Mark Grundland Color Histogram Specification by Histogram Warping
Sorry, I don't have code for that algorithm.
3 Comments
Image Analyst
on 14 Jun 2023
If youi can do it, let me know. And post it to the File Exchange. A couple of years ago I made a s tab at it and I got the first few steps done but then it got into some pretty sophisticated math that I didn't know how to translate into MATLAB so I gave it up.
See Also
Categories
Find more on Color in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!