Skip to content

Commit 7429f66

Browse files
committed
..
1 parent b4a33a9 commit 7429f66

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
title: Naive even ilumination
3+
tags: [image processing]
4+
style: fill
5+
color: success
6+
description: A simple and efficient method to correct uneven ilumination in images
7+
---
8+
9+
# Introduction
10+
11+
A way to improve uneven illumination in images → just as we can fit a line to a 1D signal, we can fit a plane to an image, as if it were a parallelepiped with a certain tilt. We convert this plane into a grayscale image, center it at 0±tol (with both negative and positive values), and add it to the grayscale channel of the unevenly illuminated image. This will make bright areas darker and dark areas brighter—or something like that. It’s like applying a proportional shadow correction to make the luminance channel more homogeneous.
12+
13+
In this post, we’ll design a simple and effective technique to enhance uneven illumination in images using plane fitting.
14+
15+
When we observe an image with uneven illumination, we often sense that something is wrong—it doesn’t look pleasing and makes it harder to perceive details. An intuitive and mathematical way to approach this problem is by fitting a plane to the image, similar to how a line is fit to a 1D signal.
16+
17+
# Theoretical Background
18+
19+
Imagine a grayscale image as a 3D surface, where each pixel has coordinates $$(x, y)$$ and an intensity $$z$$. If we fit a plane to this surface using linear regression (least squares), we obtain a representation of the general intensity trend across the image.
20+
21+
This plane can be interpreted as capturing the global illumination or tonal bias of the image. By centering this plane around zero and scaling it appropriately, we can add it to the original image to enhance intensity differences: bright areas become darker and dark areas become brighter, thus improving the homogeneity of illumination.
22+
23+
# Algorithm
24+
25+
**1. Conversion to float**
26+
27+
Convert the grayscale image to `float32` to perform numerical operations:
28+
29+
```python
30+
I = img_gray.astype(np.float32)
31+
```
32+
33+
**2. Coordinate generation**
34+
35+
Generate pixel coordinates:
36+
37+
```python
38+
ys, xs = np.mgrid[0:h, 0:w]
39+
```
40+
41+
**3. Plane fitting via least squares**
42+
43+
We want to fit a plane:
44+
45+
$$
46+
z = ax + by + c
47+
$$
48+
49+
Construct the linear system:
50+
51+
$$
52+
A \cdot
53+
\begin{bmatrix}
54+
a \\
55+
b \\
56+
c
57+
\end{bmatrix}
58+
= I,
59+
$$
60+
61+
where $$I$$ is the vector of intensities and:
62+
63+
$$
64+
A = \begin{bmatrix} x_1 & y_1 & 1 \\ x_2 & y_2 & 1 \\ \vdots & \vdots & \vdots \end{bmatrix}
65+
$$
66+
67+
Solve using least squares:
68+
69+
```python
70+
coeffs, *_ = np.linalg.lstsq(A, b, rcond=None)
71+
```
72+
73+
**4. Plane centering and normalization**
74+
75+
Center and scale the resulting plane to have zero mean and unit standard deviation (to avoid imbalanced effects):
76+
77+
```python
78+
plane_centered = plane - np.mean(plane)
79+
plane_centered /= max(np.std(plane_centered), tol)
80+
```
81+
82+
---
83+
84+
**5. Enhancement Application**
85+
86+
Counteract uneven illumination by subtracting the (scaled) plane from the original image:
87+
88+
$$
89+
I_{\text{out}} = I + \alpha \cdot \text{Plano centrado} \cdot 127
90+
$$
91+
92+
Finally, clip values to valid range and convert back to `uint8`:
93+
94+
```python
95+
I_out = np.clip(I_out, 0, 255).astype(np.uint8)
96+
```
97+
98+
# Experimentation
99+
100+
The 3D visualization helps to understand how the plane fits the image’s intensity surface and how its addition enhances illumination.
101+
102+
Testing with some synthetic images:
103+
104+
| Uneven | Heightmap and plane | Corrected |
105+
|--------|----------------------|-----------|
106+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/1.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_1.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_1.png" width="300" height="300" /> |
107+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/2.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_2.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_2.png" width="300" height="300" /> |
108+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_3.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_3.png" width="300" height="300" /> |
109+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/4.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_4.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_4.png" width="300" height="300" /> |
110+
111+
And with some real images:
112+
113+
| Uneven | Heightmap and plane | Corrected |
114+
|--------|----------------------|-----------|
115+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/5.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_5.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_5.png" width="300" height="300" /> |
116+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/6.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_6.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_6.png" width="300" height="300" /> |
117+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/7.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_7.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_7.png" width="300" height="300" /> |
118+
| <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/8.png" width="300" height="300" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/3d_surface_8.png" width="450" height="450" /> | <img src="../assets/blog_images/2025-04-22-naive-even-ilumination/perceptually_improved_8.png" width="300" height="300" /> |
119+
120+
# Conclusion
121+
122+
When vignetting is strong or the uneven distribution is very unimodal (e.g., in case 3), the method tends to perform worse than when the plane fit is clearly dominated by a directional tilt.
123+
124+
Additionally, the idea behind the model is to counteract the nearly saturated regions in the opposite way, so it’s not a very intelligent algorithm and relies on a manual parameter. However, as seen in the paper's case, it is particularly useful for specific applications where an aesthetically pleasing perception of the image is desired in real time, Avoiding uneven lighting effects characteristic of a real outdoor scene.
125+

0 commit comments

Comments
 (0)