Exposure Merge Weights
Compute pixel weights for HDR merging based on exposure quality.
In HDR imaging, we combine multiple exposures to capture scenes with high dynamic range. However, not all pixels from each exposure are equally reliable:
- Under-exposed pixels (dark, near 0) contain noise
- Over-exposed pixels (bright, near 255) are saturated/clipped
- Well-exposed pixels (mid-gray, near 128) are most reliable
We use a Gaussian weighting function centered at mid-gray:
w(z)=exp(−2σ2(z−128)2)
where:
- z is the pixel value in range [0, 255]
- σ controls the width of the acceptable exposure range
- The weight peaks at 1.0 for z = 128 and falls off for extreme values
This ensures that HDR merging prioritizes well-exposed samples while downweighting unreliable saturated or noisy regions.
Example:
exposure_weight(128, 50)
1.0
For pixel_value = 128 (mid-gray):
- Compute deviation from mid-gray: diff = 128 - 128 = 0
- Apply Gaussian formula: w = exp(-(0)² / (2 × 50²)) = exp(0) = 1.0
- The weight is maximum because mid-gray is perfectly exposed.
Constraints:
- pixel_value is an integer in range [0, 255]
- sigma is the Gaussian width parameter (positive float, default 50)
- Return weight rounded to 4 decimal places
- Weight should be in range [0, 1]
More from CV: Computational Photography
In HDR merging, we assign higher weights to mid-tone pixels (around 128) and lower weights to extreme dark/bright pixels using a Gaussian function of the pixel intensity. The problem mainly asks you to evaluate that formula for given pixel values and a chosen σ.
1. Background Knowledge
-
HDR imaging via exposure bracketing: Instead of one photo that either blows out highlights or crushes shadows, we capture several low dynamic range (LDR) images at different exposure times. Each pixel position across images will have:
-
Good detail in some exposures (well-exposed)
-
Noise in very dark exposures
-
Saturation/clipping in very bright exposures
-
Why weighting is needed: When merging, we want to trust well-exposed pixels more. A pixel close to 0 is under-exposed (noisy), close to 255 is over-exposed (clipped), and values near mid-gray (128) typically have better signal-to-noise and unsaturated detail. So each pixel gets a weight reflecting its reliability.
-
Gaussian weighting function: A Gaussian centered at mid-gray:
gives:
- Max weight 1 at z=128
- Smoothly decreasing weights as z moves away from 128
- σ controls how quickly weights drop (small σ = narrow “good” exposure band)
2. Algorithm / Approach
For this kind of problem, the general pattern is:
- Loop over all pixels in one image (or over all images if needed).
- For each pixel value z, compute its weight using the given formula.
- Optionally:
- Clamp the result to a valid range (e.g., [0, 1]) if using floating point.
- Store the weight in a separate weight map with the same size as the image.
In many HDR algorithms, you then use these weights to compute a weighted sum of pixel values across exposures and normalize by the total weight.
3. Step-by-Step Strategy
Assuming:
- Input: an 8-bit image (or array) with pixel values z∈[0,255]
- Given: σ (e.g., 20 or 30)
Steps:
- Prepare constants:
- Let mid = 128.0
- Let two_sigma2 = 2 * sigma * sigma
- Iterate over pixels:
- For each pixel intensity z (convert to float):
- Compute the difference: diff = z - mid
- Compute the exponent argument: arg = -(diff * diff) / two_sigma2
- Compute the weight: w = exp(arg)
- Store the weight:
- Place w into a weight array weights at the same pixel index.
- (If part of a full HDR pipeline):
- For each pixel location across N exposures:
where Ei is some radiance / exposure-compensated value, and wi is the computed weight.
Simple implementation sketch (per pixel):
import math
def compute_weight(z, sigma):
mid = 128.0
diff = z - mid
return math.exp(-(diff * diff) / (2.0 * sigma * sigma))
Then apply this to each pixel in the image.
4. Common Pitfalls
-
Integer vs float math: Ensure you use floating-point for the exponent calculation. Integer division will break the formula.
-
Wrong center or range:
-
The formula assumes 8-bit pixels with range [0, 255] and center at 128.
-
If the input is normalized [0, 1], you must adjust the formula (e.g., center at 0.5, and scale σ accordingly).
-
Confusing σ’s effect:
-
Too small σ → only very narrow range around 128 gets significant weight.
-
Too large σ → almost all pixels get similar weight, defeating the purpose.
-
Not handling all channels:
-
For color images, you often compute weights from luminance or one channel, not per RGB channel independently (unless specified).
5. Time & Space Complexity
-
Time complexity:
-
You compute one exponential per pixel.
-
For an image with M×N pixels:
-
Time: O(MN)
-
If there are K exposures, and you compute weights for each, then O(KMN).
-
Space complexity:
-
You need a weight value per pixel per image.
-
For one image: O(MN)
-
For K images: O(KMN) if storing all weight maps.