Engee documentation
Notebook

From daylight to sunset glow: realistic image transformation with histogram matching

This example illustrates the histogram matching technique, which is used to transform the pixel brightness distribution of one image so that it matches that of a reference image. If the images are multi-channel, the process is performed separately for each channel, provided the number of channels is matched.

Histogram matching is widely used in computer vision and image processing tasks. For example, it is indispensable when processing data acquired under different lighting conditions or from different devices such as cameras or sensors. This method allows to unify the appearance of images, which is especially important in such tasks as object recognition, image registration, and feature matching.

Examples of practical applications of histogram matching

  1. Pre-processing of medical images where it is important to maintain homogeneity of data obtained from different devices.
  2. processing of aerial and satellite images taken at different times of day or from different angles. 2.
  3. Preparing data for machine learning, where consistent image statistics contribute to improving the quality of models.

There are many applications for this technique, let's look at an example now

The task is to transform an image of a daytime landscape into a realistic sunset landscape by changing its colour palette and brightness so that the sky takes on warm shades (pink and orange) and the lighting becomes more subdued and characteristic of the evening.

Basic transformations

Import all necessary libraries

In [ ]:
import Pkg;
Pkg.add("TestImages")
Pkg.add("Images")
Pkg.add("Plots")
Pkg.add("ImageShow")
Pkg.add("ImageContrastAdjustment");
In [ ]:
using TestImages, Images, Plots
using ImageShow # Библиотека отрисовки изображений
using ImageContrastAdjustment
In [ ]:
cd( @__DIR__ )

Download images

In [ ]:
download("https://i.pinimg.com/736x/b1/bd/66/b1bd661ff2bbc212eb3f44b209c1facf.jpg", "sourse.jpg")
download("https://i.pinimg.com/736x/1a/0e/3b/1a0e3b0301e2275f81d2abdf904ec12b.jpg", "reference.jpg");

Upload images

In [ ]:
path1 = "$(@__DIR__)/sourse.jpg"
path2 = "$(@__DIR__)/reference.jpg"

sourse = load(path1)
reference = load(path2);

Visualise images

In [ ]:
simshow(sourse)
Out[0]:
No description has been provided for this image
In [ ]:
simshow(reference)
Out[0]:
No description has been provided for this image

The function adjust_histogram with the parameter Matching performs histogram matching, allowing you to transfer sunset shades to a bright daytime image. As a result, the image becomes darker.

In [ ]:
matched_image = adjust_histogram(sourse, Matching(targetimg=reference))
Out[0]:
No description has been provided for this image

Let's add pink shades to make the image sparkle with sunset colours

In [ ]:
hsv_img = map(RGB -> convert(HSV, RGB), matched_image)
evening_hsv = map(hsv -> begin
if hsv.s < 0.2 && hsv.v > 0.7  
    HSV(0.95, min(hsv.s + 0.3, 1.0), hsv.v * 0.9)  
else
    HSV(hsv.h + 0.05, hsv.s + 0.1, hsv.v * 0.7) 
end
end, hsv_img)
final_img = map(HSV -> convert(RGB, HSV), evening_hsv)
Out[0]:
No description has been provided for this image

To show the effect of histogram matching, we plot a histogram for each RGB channel.

In [ ]:
hist_final = [histogram(vec(c.(img)))
    for c in (red, green, blue)
    for img in [sourse, reference, final_img]
]

plot(
    hist_final...,
    layout = (3, 3),
    size = (800, 800),
    legend = false,
    title = ["Source" "Reference" "Histograms Matched"],
    reuse = false,
)
Out[0]:

Source:

The brightness is uniformly distributed with peaks in the middle and high intensity region (0.5-0.9), corresponding to a bright day.

Reference:

Brightness is strongly concentrated in the lower part (0.0-0.3), which corresponds to darkened areas and tones of the sunset sky.

Histograms Matched:

Histogram after histogram matching is performed. The image brightness values have been transformed to approximate the reference histogram: Brightness decreased (in the 0.0-0.3 region). The peaks in high brightness characteristic of daylight have disappeared.

Conclusion

This example shows how to transform a bright daylight image into sunset shades using histogram matching and changing the intensity of HSV channels