v9.1.1
Menu

Drago Adaptive Log Mapping

Implement Drago's adaptive logarithmic tone mapping, a technique used in tone mapping to preserve details in high dynamic range images. This method extends traditional logarithmic tone mapping by adapting the base of the logarithm based on local luminance.

The goal is to map high dynamic range images to lower dynamic ranges while preserving details, which is crucial in computational photography. The logarithmic tone mapping approach is based on the idea that human perception of light is logarithmic, and can be represented by the equation Ld=log⁡b(1+L)log⁡b(1+Lmax)L_d = \frac{\log_{b}(1 + L)}{\log_{b}(1 + L_{max})}, where LL is the luminance and bb is the adaptive base.

Here are the key steps:

  1. Compute the luminance LL from the input image.
  2. Determine the maximum luminance LmaxL_{max}.
  3. Calculate the adaptive base bb based on local luminance.
  4. Apply the logarithmic tone mapping using the calculated bb.
Ld=log⁡b(1+L)log⁡b(1+Lmax)L_d = \frac{\log_{b}(1 + L)}{\log_{b}(1 + L_{max})}

Specification

  • hdr is an RGB image of shape (H,W,3)(H, W, 3) with positive float values; values below 10−810^{-8} are raised to 10−810^{-8}.
  • Luminance: L=0.299R+0.587G+0.114BL = 0.299R + 0.587G + 0.114B.
  • Adaptive base: b=2+8⋅bias⋅log⁡2L−log⁡2Lminlog⁡2(Lmax/Lmin)b = 2 + 8 \cdot \text{bias} \cdot \frac{\log_2 L - \log_2 L_{min}}{\log_2(L_{max} / L_{min})}, so bb runs from 22 at the darkest pixel to 2+8⋅bias2 + 8 \cdot \text{bias} at the brightest.
  • Colour: multiply every channel of a pixel by Ld/LL_d / L, then clip the result to [0,1][0, 1].
  • Return a float array of the same shape (H,W,3)(H, W, 3) with values in [0,1][0, 1] (not 8-bit integers in [0,255][0, 255]).

This technique is widely used in high dynamic range imaging applications.

Example

Input
HDR image
Output
Tone mapped LDR
Reasoning
  • Input: hdr is an H×W×3H \times W \times 3 RGB radiance image of unbounded positive values; bias sets how fast the log base grows with brightness. Take gray pixels (7,7,7)(7, 7, 7) and (1,1,1)(1, 1, 1).
  • Luminance: the weights sum to 1, so gray pixels have L=7L = 7 and L=1L = 1, giving Lmax=7L_{max} = 7, Lmin=1L_{min} = 1.
  • Adaptive base: the darkest pixel gets b=2b = 2; the brightest gets b=2+8⋅0.85⋅log⁡27log⁡27=8.8b = 2 + 8 \cdot 0.85 \cdot \frac{\log_2 7}{\log_2 7} = 8.8.
  • Mapping: bright pixel Ld=log⁡8.88log⁡8.88=1L_d = \frac{\log_{8.8} 8}{\log_{8.8} 8} = 1; dark pixel Ld=log⁡22log⁡28=13L_d = \frac{\log_2 2}{\log_2 8} = \frac{1}{3}.
  • Output: scaling channels by Ld/LL_d / L gives 7⋅17=17 \cdot \frac{1}{7} = 1 and 1⋅13≈0.33331 \cdot \frac{1}{3} \approx 0.3333, so the Tone mapped LDR image has pixels (1,1,1)(1, 1, 1) and (0.3333,0.3333,0.3333)(0.3333, 0.3333, 0.3333): same shape, floats in [0,1][0, 1].
  • Notice: each pixel's base appears top and bottom, so by change of base Ld=ln⁡(1+L)ln⁡(1+Lmax)L_d = \frac{\ln(1 + L)}{\ln(1 + L_{max})}. The brightest pixel always maps to 1; a 7×7\times radiance gap shrinks to 3×3\times.

Constraints

  • Input image: 2D numpy array (grayscale or RGB) with shape (height, width) and dtype float32, representing the high dynamic range image
  • Luminance values: in range [0, 1e6], assuming a maximum possible luminance of 1 million
  • Adaptive base calculation: b in range [2, 10], with a minimum and maximum base value to prevent division by zero and ensure meaningful tone mapping
  • Output: return the tone mapped image as a 2D numpy array (grayscale or RGB) with the same shape as the input, and dtype uint8, representing the low dynamic range image
  • Special conditions: assume the input image has at least one pixel with a non-zero luminance value to avoid division by zero in the logarithmic tone mapping equation

Learn this in

More from CV: Computational Photography

PRO

Editor locked

The code editor is locked for Pro problems. It is only available for free problems. Please upgrade to gain access to the code editor for all problems.

solution.py

Test results

Sign in to run your code against the test cases.