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
- Medical image preprocessing, where it is important to maintain homogeneity of data from different devices.
- processing of aerial and satellite images taken at different times of day or from different angles. 2.
- 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
import Pkg;
Pkg.add("TestImages")
Pkg.add("Images")
Pkg.add("Plots")
Pkg.add("ImageShow")
Pkg.add("ImageContrastAdjustment");
using TestImages, Images, Plots
using ImageShow # Библиотека отрисовки изображений
using ImageContrastAdjustment
cd( @__DIR__ )
Download images
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
path1 = "$(@__DIR__)/sourse.jpg"
path2 = "$(@__DIR__)/reference.jpg"
sourse = load(path1)
reference = load(path2);
Visualise images
simshow(sourse)
simshow(reference)
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.
matched_image = adjust_histogram(sourse, Matching(targetimg=reference))
Let's add pink shades to make the image sparkle with sunset colours
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)
To show the effect of histogram matching, we plot a histogram for each RGB channel.
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,
)
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