A Simple Image Brightness and Contrast Adjustment Technique

yurivish2 pts0 comments

A Simple Image Brightness And Contrast Adjustment Technique – Geo's Notepad – Mostly Programming and Math

-->

-->

A Simple Image Brightness And Contrast Adjustment Technique

Posted 2026-05-18

I recently found myself squinting at two images at work and wondering if one<br>is actually “better” than the other. The two images were<br>showing the same object, but they had slightly but noticeably different value<br>ranges. That made it hard for me to understand which of the differences were<br>due to display brightness and contrast settings and which were part of the<br>actual structure of the image. Then I remembered a simple technique that<br>I’ve been using on and off since my PhD days.

The Problem

So let’s say we have two images \(\boldsymbol{I}\) and \(\boldsymbol{J}\) we<br>want to normalize to a common brightness range. Despite showing the same<br>structures, maybe we have generated the two images using slightly different<br>processing techniques. The structures of interest might present a little differently,<br>but the value ranges might also be shifted noticeably between the images. Using<br>the minimum and maximum values to normalize the value ranges is often a bad idea<br>because those properties can be very sensitive to noise. On the other hand,<br>using the mean or mode to scale one image to the other is often good enough,<br>but gives us only one degree of freedom. Note that we assume that the images<br>are spatially aligned and the only thing we want to correct is a brightness<br>transform.

A Simple Brightness Transform

Now let’s find a simple brightness transform that maps image \(\boldsymbol{J}\)<br>to image \(\boldsymbol{I}\). Let’s allow a linear brightness transform with<br>coefficients because such a transform is typically so constrained that it won’t<br>alter the structures of interest. It will only help us shift one image to the<br>value range of the other image to make it comparable. Every pixel<br>\(J_k\) at index \(k\) of image \(\boldsymbol{J}\) is transformed as1:

\[J_k \mapsto a J_k + b, \tag{1} \label{transform}\]

where \(a, b \in \mathbb{R}\) are the coefficients of the transformation.<br>So, what are the best coefficients \(a, b\) such that the brightness<br>variations between the images are minimized? Well, we can, e.g., minimize<br>the pixelwise deviations of the images in a least squares sense2:

\[\min_{a,b} \frac{1}{N} \sum_{k=1}^{N} \left( a J_k +b - I_k \right)^2 \tag{2} \label{ols}\]

The neat thing is that there’s an analytical solution for the coefficients,<br>which can be found by simply calculating the point at which the partial<br>derivatives \(\partial/\partial a, \partial/\partial b\) of the expression<br>both vanish. After some rewriting, this leads us to:

\[\begin{eqnarray}<br>a &=& \frac{\text{cov}(\boldsymbol{I},\boldsymbol{J})}{\text{var}(\boldsymbol{J})} \label{a-ols} \tag{3a}\\<br>b &=& \text{mean}(\boldsymbol{I}) - a\cdot \text{mean}(\boldsymbol{J}) \label{b-ols} \tag{3b},<br>\end{eqnarray}\]

where \(\text{mean}\) calculates the mean value of an image,<br>\(\text{cov}\) is the covariance,<br>and \(\text{var}\) is the variance:

\[\begin{eqnarray}<br>\text{mean}(\boldsymbol{I}) &=& \frac{1}{N} \sum_{k=1}^{N} I_k \tag{4a} \label{mean}\\<br>\text{cov}(\boldsymbol{I},\boldsymbol{J}) &=& \frac{1}{N-1} \sum_{k=1}^{N} (I_k-\text{mean}(\boldsymbol{I}))\cdot(J_k- \text{mean}(\boldsymbol{J})) \tag{4b} \label{cov}\\<br>\text{var}(\boldsymbol{J}) &=& \text{cov}(\boldsymbol{J},\boldsymbol{J}) \tag{4c} \label{var}<br>\end{eqnarray}\]

That means using eq. \(\eqref{transform}\) with coefficients from \(\eqref{a-ols}\)<br>and \(\eqref{b-ols}\) to adjust the brightness values in image \(\boldsymbol{J}\)<br>will adjust the image to fit the brightness range of image \(\boldsymbol{I}\).

Weighted Least Squares

There’s one more improvement to the technique we can make quite easily, which<br>is to use weighted least squares as the minimization objective rather than<br>the ordinary least squares we used above. This allows us to give each<br>pixel \(k\) a corresponding weight \(w_k\) that modifies its contribution to<br>the objective function. For example, if our images contain large areas of<br>near-zero background, we could force areas with higher signal to contribute<br>more strongly by setting the weights as \(w_k = I_k\); we could also set the<br>weights for pixels below a threshold to \(0\). There are many possible<br>ways to improve the optimization with weighting.

For weighted least squares, our minimization objective becomes

\[\min_{a,b} \frac{1}{N} \sum_{k=1}^{N} w_k \left( a J_k +b - I_k \right)^2 \tag{5} \label{wls},\]

and we can find very similar analytical solutions for the coefficients

\[\begin{eqnarray}<br>a &=& \frac{\text{cov}_{\boldsymbol{w}}(\boldsymbol{I},\boldsymbol{J})}{\text{var}_{\boldsymbol{w}}(\boldsymbol{J})} \label{a-wls} \tag{6a}\\<br>b &=& \text{mean}_{\boldsymbol{w}}(\boldsymbol{I}) - a\cdot \text{mean}_{\boldsymbol{w}}(\boldsymbol{J}) \label{b-wls} \tag{6b}.<br>\end{eqnarray}\]

Now we have to use the weighted mean, covariance, and variance defined...

boldsymbol text image brightness mean label

Related Articles