Tool Idea - Color Harmonizer

Color Hamronizer

Introduction

Here is an idea for a color processing tool I had about a year ago. I often like to tone images based on the prevalent colors in an image. What I normally try is to pull adjacent colors towards a selected color in order to get a more harmonious image. This can be done with various tools from various softwares (eg. in Rawtherapee’s LAB-Tool I use the HH curve). But it would be nice if I could select the color (the other colors are pulled towards) directly in the image.
I have written a little Python script which works on very small images, but I would like to see it usable for larger (normal) images as well. I started to refresh my non existing C++ skills in attempt to maybe integrate it into RT someday, but this is not realistic as work and family take up to much time at the moment to do anything else with some intensity.

So I will share the idea and the existing script here to maybe inspire somebody!

Basic Idea

The idea is to take a color space like LAB, which has a two dimensional color plain (A, B) detached from the luminosity (L). The idea is to select a so called pull color from the image itself, and all other colors are then pulled towards the pull color. The amount of pull is defined by a strength. If two or more pull colors are selected, then each other color is pulled towards its closest pull color.
So how do I define a “closest” color?
That depends on the color space. Ideally it is done in a color space like LAB were you have a plane that defines all the colors and is detached from the luminosity.

Rough Script

A very rough working script in python using OpenCV is available here:

The program allows to select pull colors by clicking on the image itself. It allows up to three pull colors.

  • The first pull color is selected by a left mouse click.
  • The second pull color is selected by a right mouse click.
  • The third pull color is selected by a click on the mouse wheel.
    You can set the strength of the pull, the number of pull points and a blur, which I will explain later.

The program basically looks where the selected pull color is located in Lab’s AxB-plane an geometrically selects which colors are pulled towards which pull color.

Examples

The first row of images shows the effect of selecting one pull color. On the left is the original image.
I select one color and gradually increase the strength from left to right.
[outflie_cl1_str]

The next row shows the effect of selecting two colors with 100% strength. The first image has no blur. Then blur is increased towards the right.
[outfile_cl2_blur]

The next row shows two colors selected with a full blur and then the strength is decreased.
[outfile_cl2_str]

Examples with a real image

The next imagess show possible applications to a real image.
Here I select the red from the coat and increase the strength:
[outimage_cl1_row]

Next I select the red from the coat and the blue from the jeans and apply full strength at first and then gradually increase the blur:
[outimage_cl2_str100_bl0_2_4_8]

Here again the red and blue colors selected with a blur of 4 while increasing the strength from 0 to 100:
[outimage_cl2_bl4_str0_20_40_60_100]

Last I select a third color, the green grass. The strength is set to 100 and the blur is increased from 0 to 4. The original image is on the right for comparison.
[outimage_cl3_str100_bl0_2_4_original]

Further ideas

  • Select one color from image and automatically create the other pull colors based on color harmonies (complementary, tertiary, etc…)
  • make it possible to select wether a pull color will just adjust the tone of other colors while keeping it’s saturation, or if it should also change the saturation
  • make it possible to select the colors from a color gradient instead of selecting them from the image.
  • and obviously make so that everything stays within gamut…
6 Likes

Interesting. I don’t understand the effect of “blur”, and I don’t read Python. Can you explain further?

Aside from that, it would be easy to implement in ImageMagick, once the three colours are specified.

  1. Convert to Lab.
  2. “-remap” the image to the three colours.
  3. Blend between the outputs of (1) and (2).
  4. If desired, for each pixel set the chroma (approx “saturation”) of the result to the chroma of the input pixel.

I’ve been(sort of) getting this effect in dakrable using Color Balance RGB’s 4 way tab, selecting the color I want using the Hue slider, then using the chroma slider to change the color. The more chroma, the closer the colors are. Since I don’t generally want 100% uniformity, I’ll use a blend mode like average.

Could you show one of those edits when you get a chance…

Why not just halve the % of your chroma slider instead?

Its late but I don’t think it would be the same…

Random LCh color 33 64 312 is rgb of 102 51 153… so averaging that by blending to a random rgb pixel of say 25 50 100 would not be the same as directly applying the module with LCh 33 32 312 which would be around 93 66 115 as an rgb value… I don’t think but its late and I should be in bed :slight_smile:

1 Like

I use all four sliders, adjust them to taste. Backing off all of them some percentage doesn’t generally give me what I want.

The effect for me now has too much chroma strength. It looks a little too unnatural.

What I’d really want is to (1) select a range of color, ala the hue selector in the mask module. (2) select the color to push towards (3) some slider to choose how close to the target the select range of colors is

I wonder if there is any mileage left in this module. If you used it later in the pipeline and sampled a color gradient swatch. Then used it… I only ever tried it like the example in the manual but I never though about some of those color gradients that you can generate… I think Boris did some experimentations with complimentary colors etc …not like this but discussing resources to create them…

Maybe those skilled with luts would just use one instead ??

1 Like

With G’MIC you can do this with this filter:

Have been testing colorbalance rgb with average blend mode, its a neat little trick! Difference is subtle (when values are doubled), but haven’t seen it give worse results than normal blend mode yet, and indeed often gives better.

I’ve been playing with the colorize module and hue masks, which I think gets somewhat close to the goal of this thread (albeit painfully, as the HSL values given for colours on the net don’t display the same result when used in colorize, nor do the HSL values entered in colorize match those displayed in the color picker. Don’t want to hijack this thread, but it might be worth starting a new one to work out what’s going on in that module. An RGB version of colorize would be great.)

1 Like

If you look at the second row of images. The leftmost image ist the original. I then select the red (top right corner) and the blue (bottom left corner). With strength set to 100% the second image in that row is created. Basically all colors closest to the red become red and all colors closest to the blue become blue.
The transition is sharp. To the get a smooth transition between the to colors I use a blur. The other three images in that same row show the effect of increasing the blur.

The same is shown for the real image in the second row. In the leftmost image I have selected to colors (the red of the cape and the blue of the jeans) and set the strength to 100%. As you can see the are sharp transitions from one color to another again. To smooth this out and make it mor pleasant I increase the blur (the three images to the right).

I also just remebered that my original idea was to select one color directly from the image to then automatically create color harmonies based on complementary, tertiary, etc…

Oh and a very friendly person on github just improved my script and it now works on full scale images :smiley:

1 Like

On first try it didn’t get me where I wanted very fast. But it was only a first try and I will have to play a bit more with it.

1 Like