Bug fixes and worked more on Debevec algorithm, updated Documentation
This commit is contained in:
@@ -6,15 +6,15 @@
|
||||
[](https://github.com/comfyanonymous/ComfyUI)
|
||||
[](https://github.com/sumitchatterjee13/Luminance-Stack-Processor)
|
||||
|
||||
HDR (High Dynamic Range) processing nodes for ComfyUI featuring my **Detail Injection** algorithm (default) and **Radiance Fusion Algorithm** - custom HDR processing methods that deliver good results for both AI-generated and real-world images.
|
||||
HDR (High Dynamic Range) processing nodes for ComfyUI featuring **Detail Injection** algorithm (default) and **Radiance Fusion Algorithm** - custom HDR processing methods that work well for both AI-generated and real-world images.
|
||||
|
||||
**Version: 1.1.8** | **Release Date: 2025-10-02**
|
||||
|
||||
## 🎯 Features
|
||||
|
||||
- **🎨 DETAIL INJECTION ALGORITHM** *(DEFAULT since v1.1.3)*: Revolutionary AI-aware HDR processing
|
||||
- **Perfect for AI-Generated Images**: Specifically designed for AI exposure stacks
|
||||
- **Now the default algorithm**: Best results out-of-the-box
|
||||
- **🎨 DETAIL INJECTION ALGORITHM** *(DEFAULT since v1.1.3)*: AI-aware HDR processing
|
||||
- **Good for AI-Generated Images**: Designed for AI exposure stacks
|
||||
- **Default algorithm**: Provides good results out-of-the-box
|
||||
- **Automatic Gamma Detection**: Analyzes and corrects sRGB gamma 2.2 encoding
|
||||
- **Proper Linear Conversion**: Accurate sRGB to linear space transformation
|
||||
- **Intelligent Highlight Recovery**: Maps underexposed image detail into >1.0 HDR range
|
||||
@@ -24,15 +24,15 @@ HDR (High Dynamic Range) processing nodes for ComfyUI featuring my **Detail Inje
|
||||
- **Hermite Interpolation**: Smooth blending prevents harsh transitions
|
||||
- **EV0 Base Preservation**: Keeps natural appearance while extending dynamic range
|
||||
- **Linear HDR Output**: True HDR values for professional EXR export
|
||||
- **🚀 RADIANCE FUSION ALGORITHM**: My custom HDR algorithm
|
||||
- **🚀 RADIANCE FUSION ALGORITHM**: Custom HDR algorithm
|
||||
- **Nuke-Inspired Mathematics**: Based on VFX pipeline operations (plus/average)
|
||||
- **Enhanced HDR Preservation**: Maintains excellent dynamic range with natural appearance
|
||||
- **Improved Results**: Provides quality improvements over traditional methods
|
||||
- **HDR Preservation**: Maintains good dynamic range with natural appearance
|
||||
- **Alternative Results**: Provides different approach compared to traditional methods
|
||||
- **For VFX Work**: Suitable for compositing workflows
|
||||
- **🆕 TRUE 32-bit EXR Export**: Professional bit-depth control with imageio integration
|
||||
- **🚨 TRUE HDR Values Above 1.0**: Proper HDR data preservation without normalization
|
||||
- **🔬 DEBEVEC WITH ADAPTIVE CALIBRATION** *(Experimental)*:
|
||||
- **AI-Aware Calibration**: Automatically analyzes and corrects exposure relationships for AI-generated images
|
||||
- **AI-Aware Calibration**: Analyzes and corrects exposure relationships for AI-generated images
|
||||
- **Physically-Based Recovery**: True linear radiance output
|
||||
- **Anti-Banding Filtering**: Subtle bilateral filtering reduces quantization artifacts
|
||||
- **Exposure Compensation**: Built-in -8 stop default for proper viewing in Nuke/Resolve
|
||||
@@ -53,7 +53,7 @@ HDR (High Dynamic Range) processing nodes for ComfyUI featuring my **Detail Inje
|
||||
|
||||
### HDR Processing Comparison
|
||||
|
||||
See the dramatic difference my Radiance Fusion Algorithm makes in preserving detail across exposure ranges:
|
||||
See the difference the Radiance Fusion Algorithm makes in preserving detail across exposure ranges:
|
||||
|
||||
#### Indoor Lighting Comparison
|
||||

|
||||
@@ -73,9 +73,9 @@ These comparison strips demonstrate how my HDR processing maintains detail in bo
|
||||
|
||||
### 🎨 Detail Injection Algorithm (Default)
|
||||
|
||||
**What makes Detail Injection special?**
|
||||
**What makes Detail Injection different?**
|
||||
|
||||
Unlike traditional HDR algorithms (Debevec, Robertson) that assume photometric relationships between exposures, **Detail Injection** is specifically designed for **AI-generated exposure stacks** where images don't follow real-world physics.
|
||||
Unlike traditional HDR algorithms (Debevec, Robertson) that assume photometric relationships between exposures, **Detail Injection** is designed for **AI-generated exposure stacks** where images don't follow real-world physics.
|
||||
|
||||
#### **The Problem It Solves:**
|
||||
|
||||
@@ -107,21 +107,21 @@ AI-generated images simulate different exposures but don't have true photometric
|
||||
**Step 4: Automatic Brightness Compensation** 🎚️
|
||||
- Analyzes median/mean values
|
||||
- Targets **0.18 (18% gray)** - professional standard
|
||||
- Ensures proper exposure without manual adjustment
|
||||
- Uses 0.3x-8.0x range for extreme correction capability
|
||||
- Helps with proper exposure without manual adjustment
|
||||
- Uses 0.3x-8.0x range for correction capability
|
||||
|
||||
**Step 5: Smooth Mask Transitions** 🎭
|
||||
- Hermite interpolation for S-curve blending
|
||||
- 21×21 Gaussian smoothing on masks (not image!)
|
||||
- Gradual feathering over wide tonal ranges
|
||||
- No visible blend boundaries
|
||||
- Helps reduce visible blend boundaries
|
||||
|
||||
#### **Why Use Detail Injection?**
|
||||
|
||||
✅ **For AI-Generated HDR Stacks**: Works well with Flux, SD, MJ exposure variations
|
||||
✅ **For AI-Generated HDR Stacks**: Works with Flux, SD, MJ exposure variations
|
||||
✅ **Natural EV0 Base**: Looks correct at middle exposure
|
||||
✅ **True HDR Range**: Values >1.0 for color grading workflows
|
||||
✅ **Automatic Exposure**: No manual brightness adjustment needed
|
||||
✅ **Automatic Exposure**: Helps with brightness adjustment
|
||||
✅ **Smooth Blending**: Reduces harsh transitions and artifacts
|
||||
✅ **Color Accuracy**: Maintains hue using luminance-based scaling
|
||||
|
||||
@@ -137,7 +137,7 @@ AI-generated images simulate different exposures but don't have true photometric
|
||||
|
||||
### 🔬 Debevec with Adaptive Calibration (NEW!)
|
||||
|
||||
**Revolutionary approach to HDR recovery for AI-generated images!**
|
||||
**Adaptive approach to HDR recovery for AI-generated images!**
|
||||
|
||||
Traditional Debevec algorithm assumes **photometric consistency** - that brightness relationships follow physics:
|
||||
```
|
||||
@@ -149,7 +149,7 @@ But **AI-generated images don't follow these rules!** Each exposure is independe
|
||||
|
||||
#### **My Solution: Adaptive Exposure Calibration**
|
||||
|
||||
I've developed an intelligent calibration system that **automatically analyzes and corrects** the exposure relationships:
|
||||
I've developed a calibration system that **analyzes and corrects** the exposure relationships:
|
||||
|
||||
**Step 1: Analyze Actual Brightness Relationships**
|
||||
```python
|
||||
@@ -252,7 +252,7 @@ Applied exposure compensation: -8.0 stops (factor: 0.003906x)
|
||||
Debevec compensated output: [0.00004, 454.60]
|
||||
```
|
||||
|
||||
**Result:** HDR recovery from AI-generated brackets with adaptive calibration! 🎯
|
||||
**Result:** HDR recovery from AI-generated brackets with adaptive calibration.
|
||||
|
||||
---
|
||||
|
||||
@@ -413,7 +413,7 @@ For extended dynamic range with 5 exposures:
|
||||
|
||||
### 🆕 Latent Stack Processor (5 Stops)
|
||||
|
||||
**NEW!** Fast latent-space processing with **intelligent noise reduction**:
|
||||
**NEW!** Fast latent-space processing with **noise reduction**:
|
||||
|
||||
**What it does:**
|
||||
- Performs weighted averaging of latent representations with multiple blend modes
|
||||
@@ -436,9 +436,8 @@ For extended dynamic range with 5 exposures:
|
||||
|
||||
**🎯 Blend Modes (Noise & Artifact Reduction Strategies):**
|
||||
|
||||
1. **`quality_aware`** 👑🏆 (Default, Ultimate Solution!)
|
||||
- **Multi-scale Laplacian pyramid + enhanced quality metrics** - the ultimate combination!
|
||||
- **Merges the best technologies**: Frequency decomposition + sophisticated quality analysis
|
||||
1. **`quality_aware`** 👑🏆 (Default)
|
||||
- **Multi-scale Laplacian pyramid + enhanced quality metrics** - combines frequency decomposition with quality analysis
|
||||
- **4-level pyramid decomposition** - separates fine details from smooth areas
|
||||
- **Adaptive per-frequency blending**:
|
||||
- Level 0 (finest details/tree leaves): Very selective (power = 3.8x with default settings)
|
||||
@@ -449,8 +448,8 @@ For extended dynamic range with 5 exposures:
|
||||
- Contrast: 60% weight (edges/details prioritized)
|
||||
- Saturation: 25% weight (color richness)
|
||||
- Exposedness: 15% weight (well-exposed regions)
|
||||
- **Result:** Tree leaves perfectly sharp, sky smooth, zero artifacts!
|
||||
- **Use when:** You want professional, artifact-free results (DEFAULT!) 👑
|
||||
- **Result:** Tree leaves sharp, sky smooth, reduced artifacts!
|
||||
- **Use when:** You want good results with reduced artifacts (DEFAULT!) 👑
|
||||
- **Parameters:**
|
||||
- `detail_preservation` (0.0-1.0, default 0.7): Controls selectivity sharpness
|
||||
- `center_bias` (0.0-0.8, default 0.4): Boosts center exposure baseline quality
|
||||
@@ -487,9 +486,9 @@ For extended dynamic range with 5 exposures:
|
||||
- **Use when:** Input latents are already clean
|
||||
|
||||
**💡 Artifact & Noise Reduction Tips:**
|
||||
- **Use `quality_aware`** (DEFAULT) 👑 - ultimate multi-scale solution with enhanced quality metrics!
|
||||
- **For tree leaf ghosting**: Multi-scale pyramid completely eliminates this - finest details use highest power selectivity
|
||||
- **Default settings work great** - adaptive quality power per frequency automatically handles everything
|
||||
- **Use `quality_aware`** (DEFAULT) 👑 - multi-scale solution with enhanced quality metrics
|
||||
- **For tree leaf ghosting**: Multi-scale pyramid helps reduce this - finest details use highest power selectivity
|
||||
- **Default settings work well** - adaptive quality power per frequency handles most cases
|
||||
- **Optional tuning:**
|
||||
- Increase `detail_preservation` (0.8-0.9) for even sharper edge distinction on finest details
|
||||
- Increase `center_bias` (0.5-0.7) to boost center exposure baseline quality across all levels
|
||||
@@ -511,14 +510,14 @@ For extended dynamic range with 5 exposures:
|
||||
- Increase `detail_preservation` (0.8-0.9) for even sharper edge selectivity
|
||||
- Increase `center_bias` (0.5-0.7) to boost center exposure across all pyramid levels
|
||||
6. Decode the merged latent with VAE Decode
|
||||
7. Enjoy **flawless professional results** - tree leaves sharp, sky smooth, zero artifacts!
|
||||
7. Enjoy **good results** - tree leaves sharp, sky smooth, reduced artifacts!
|
||||
|
||||
### 📋 **Complete HDR Workflow Example:**
|
||||
|
||||
1. **Load Images**: Load your bracketed exposures (3 or 5 images)
|
||||
2. **Add Processing Node**: "Luminance Stack Processor (3/5 Stops)"
|
||||
3. **Connect Exposures**: Connect each EV image to corresponding input
|
||||
4. **Choose Algorithm**: Select HDR algorithm (**Radiance Fusion recommended - my custom algorithm**)
|
||||
4. **Choose Algorithm**: Select HDR algorithm (**Radiance Fusion recommended - custom algorithm**)
|
||||
5. **Add Export Node**: "HDR Export to EXR"
|
||||
6. **Connect HDR Output**: From processor to export node
|
||||
7. **Set Filename**: Enter desired filename prefix
|
||||
@@ -527,22 +526,22 @@ For extended dynamic range with 5 exposures:
|
||||
|
||||
## 🔬 How It Works
|
||||
|
||||
The nodes feature my **Radiance Fusion Algorithm** as the default, plus traditional algorithms for compatibility:
|
||||
The nodes feature the **Radiance Fusion Algorithm** as the default, plus traditional algorithms for compatibility:
|
||||
|
||||
1. **Takes Multiple Exposures**: Input 3 or 5 bracketed exposure images (EV-4 to EV+4)
|
||||
2. **Selects HDR Algorithm**: Choose **Radiance Fusion** (my custom algorithm) or traditional methods
|
||||
2. **Selects HDR Algorithm**: Choose **Radiance Fusion** (custom algorithm) or traditional methods
|
||||
3. **Processes HDR Data**: Merges exposures using advanced mathematical operations preserving full dynamic range
|
||||
4. **Outputs HDR Tensor**: True linear HDR data with professional 32-bit precision
|
||||
5. **🚨 CRITICAL: Use HDR Export Node**: Exports professional 32-bit EXR files with preserved HDR values
|
||||
|
||||
### 🎯 **HDR Algorithm Options:**
|
||||
|
||||
#### **🚀 Radiance Fusion (Default - My Custom Algorithm)**
|
||||
#### **🚀 Radiance Fusion (Default - Custom Algorithm)**
|
||||
- **📈 HDR Range**: Wide dynamic range with good preservation
|
||||
- **🧮 Advanced Mathematics**: Nuke-inspired plus/average operations for enhanced results
|
||||
- **🧮 Mathematics**: Nuke-inspired plus/average operations
|
||||
- **🎬 Quality**: VFX-oriented HDR processing with natural appearance
|
||||
- **⚡ Good Performance**: Well-balanced dynamic range and visual appeal
|
||||
- **🔬 In-House Development**: My custom algorithm with improvements over traditional methods
|
||||
- **⚡ Performance**: Well-balanced dynamic range and visual appeal
|
||||
- **🔬 Custom Development**: Custom algorithm with improvements over traditional methods
|
||||
- **💎 Quality Focus**: Enhanced compared to standard techniques
|
||||
|
||||
---
|
||||
@@ -781,4 +780,4 @@ I welcome contributions! Please:
|
||||
|
||||
---
|
||||
|
||||
**Happy HDR Processing with Radiance Fusion!** 🚀✨ | **Version 1.0.5** | **Featuring My Custom Algorithm**
|
||||
**Happy HDR Processing with Radiance Fusion!** 🚀✨ | **Version 1.1.8** | **Featuring Custom Algorithm**
|
||||
|
||||
@@ -134,58 +134,80 @@ class DebevecHDRProcessor:
|
||||
"""Core HDR processing using multiple algorithms"""
|
||||
|
||||
def __init__(self):
|
||||
self.calibrator = cv2.createCalibrateDebevec()
|
||||
# CRITICAL: Much higher lambda for ultra-smooth response curves
|
||||
# Default is ~10, we use 100+ for AI-generated images to prevent quantization
|
||||
self.calibrator = cv2.createCalibrateDebevec(samples=200, lambda_=100.0)
|
||||
self.merge_debevec = cv2.createMergeDebevec()
|
||||
# Alternative algorithms
|
||||
self.merge_mertens = cv2.createMergeMertens()
|
||||
self.merge_robertson = cv2.createMergeRobertson()
|
||||
self.calibrator_robertson = cv2.createCalibrateRobertson()
|
||||
logger.info("Debevec calibrator configured with ultra-high smoothness (lambda=100.0, samples=200)")
|
||||
|
||||
def _apply_antibanding_filter(self, hdr_image: np.ndarray) -> np.ndarray:
|
||||
def _apply_gradient_adaptive_dithering(self, hdr_image: np.ndarray) -> np.ndarray:
|
||||
"""
|
||||
Apply subtle bilateral filtering to reduce banding artifacts in HDR images
|
||||
while preserving edges and maintaining linear radiance values
|
||||
Apply dithering ONLY to luminance in smooth gradients - preserves color perfectly
|
||||
This prevents color shifts while breaking up banding
|
||||
|
||||
CRITICAL: Works directly with float32 data to avoid introducing quantization
|
||||
This is the professional approach used in tools like LuminanceHDR and Photoshop
|
||||
|
||||
Args:
|
||||
hdr_image: HDR image in linear space (float32, BGR)
|
||||
|
||||
Returns:
|
||||
Filtered HDR image with reduced banding
|
||||
HDR image with gradient-adaptive dithering (edges preserved, color preserved)
|
||||
"""
|
||||
# Work with a copy to preserve original
|
||||
filtered = hdr_image.copy()
|
||||
logger.info("Applying luminance-based gradient-adaptive dithering (color-preserving)...")
|
||||
|
||||
# Normalize to 0-1 range for bilateral filter
|
||||
max_val = np.percentile(hdr_image, 99.9) # Use 99.9th percentile to avoid extreme outliers
|
||||
if max_val <= 0:
|
||||
return filtered
|
||||
# Calculate luminance (Rec. 709)
|
||||
# Note: hdr_image is in BGR format from OpenCV
|
||||
luminance = (0.0722 * hdr_image[:, :, 0] + # B
|
||||
0.7152 * hdr_image[:, :, 1] + # G
|
||||
0.2126 * hdr_image[:, :, 2]) # R
|
||||
|
||||
normalized = np.clip(hdr_image / max_val, 0, 1).astype(np.float32)
|
||||
# Calculate gradient magnitude on luminance
|
||||
grad_x = cv2.Sobel(luminance, cv2.CV_32F, 1, 0, ksize=3)
|
||||
grad_y = cv2.Sobel(luminance, cv2.CV_32F, 0, 1, ksize=3)
|
||||
gradient_magnitude = np.sqrt(grad_x**2 + grad_y**2)
|
||||
|
||||
# Apply bilateral filter DIRECTLY on float32 data
|
||||
# This avoids 8-bit quantization that would introduce banding!
|
||||
# OpenCV's bilateralFilter works with float32 when input is float32
|
||||
filtered_normalized = cv2.bilateralFilter(
|
||||
normalized,
|
||||
d=5, # Small kernel - very subtle
|
||||
sigmaColor=0.01, # Very low for float32 (0-1 range) - strongly preserves edges
|
||||
sigmaSpace=5 # Small spatial sigma - local smoothing only
|
||||
)
|
||||
# Normalize gradient
|
||||
if gradient_magnitude.max() > 0:
|
||||
gradient_norm = gradient_magnitude / gradient_magnitude.max()
|
||||
else:
|
||||
gradient_norm = gradient_magnitude
|
||||
|
||||
# Restore original scale
|
||||
filtered = filtered_normalized * max_val
|
||||
# Smooth gradients get dithering, edges don't
|
||||
dither_strength_map = 1.0 - gradient_norm
|
||||
dither_strength_map = cv2.GaussianBlur(dither_strength_map, (5, 5), 1.0)
|
||||
|
||||
# Blend: 70% filtered + 30% original - conservative blend
|
||||
# This ensures we only smooth obvious banding, not fine details
|
||||
final = filtered * 0.7 + hdr_image * 0.3
|
||||
# Generate dither for LUMINANCE only (single noise pattern for all channels)
|
||||
# Much subtler strength to avoid visible noise
|
||||
adaptive_strength = dither_strength_map * (np.abs(luminance) + 0.01) * 0.0008 # 0.08% instead of 0.3%
|
||||
|
||||
logger.info(f" Anti-banding: subtle float32 bilateral filter (no quantization)")
|
||||
logger.info(f" Blend: 70% filtered + 30% original (preserves detail)")
|
||||
logger.info(f" Preserved HDR peaks: max value {final.max():.2f}")
|
||||
# Single noise pattern
|
||||
noise = np.random.normal(0, 1, luminance.shape).astype(np.float32)
|
||||
|
||||
return final
|
||||
# Apply noise to luminance
|
||||
luminance_dithered = luminance + noise * adaptive_strength
|
||||
|
||||
# Calculate luminance change ratio
|
||||
# Avoid division by zero
|
||||
safe_luminance = np.maximum(luminance, 1e-6)
|
||||
luma_ratio = luminance_dithered / safe_luminance
|
||||
|
||||
# Apply same ratio to all color channels - preserves color perfectly!
|
||||
result = hdr_image.copy()
|
||||
for c in range(3):
|
||||
result[:, :, c] = hdr_image[:, :, c] * luma_ratio
|
||||
|
||||
# Statistics
|
||||
smooth_pixels = np.sum(dither_strength_map > 0.5)
|
||||
total_pixels = dither_strength_map.size
|
||||
logger.info(f" Luminance dithering: {smooth_pixels}/{total_pixels} smooth pixels ({100*smooth_pixels/total_pixels:.1f}%)")
|
||||
logger.info(f" Color preservation: 100% (luminance-only dithering)")
|
||||
logger.info(f" Dither strength: 0.08% (very subtle, imperceptible)")
|
||||
|
||||
return result.astype(np.float32)
|
||||
|
||||
def _compute_exposure_ratio_srgb(self, reference: np.ndarray, target: np.ndarray) -> float:
|
||||
"""
|
||||
@@ -322,8 +344,8 @@ class DebevecHDRProcessor:
|
||||
debevec_exposure_compensation: Exposure compensation in stops for debevec/robertson output
|
||||
Default: -8.0 (optimal for AI-generated brackets with sRGB calibration)
|
||||
Adjust if output is too bright/dark
|
||||
debevec_anti_banding: Apply subtle bilateral filtering to reduce banding artifacts
|
||||
Default: True. Preserves edges while smoothing gradients.
|
||||
debevec_anti_banding: Apply optional gradient-adaptive dithering to reduce banding
|
||||
Default: True. Disable for pure lambda=100 smoothness with no color changes.
|
||||
|
||||
Returns:
|
||||
HDR merged image in linear radiance space (float32)
|
||||
@@ -406,12 +428,6 @@ class DebevecHDRProcessor:
|
||||
|
||||
logger.info(f"Robertson raw output: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
|
||||
|
||||
# Anti-banding filter
|
||||
if debevec_anti_banding:
|
||||
logger.info("Applying anti-banding bilateral filter...")
|
||||
hdr_radiance = self._apply_antibanding_filter(hdr_radiance)
|
||||
logger.info(f"After anti-banding: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
|
||||
|
||||
# Apply exposure compensation
|
||||
if debevec_exposure_compensation != 0.0:
|
||||
compensation_factor = 2.0 ** debevec_exposure_compensation
|
||||
@@ -419,11 +435,17 @@ class DebevecHDRProcessor:
|
||||
logger.info(f"Applied exposure compensation: {debevec_exposure_compensation:+.1f} stops (factor: {compensation_factor:.6f}x)")
|
||||
logger.info(f"Robertson compensated output: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
|
||||
|
||||
# Apply gradient-adaptive dithering if anti-banding is enabled
|
||||
if debevec_anti_banding:
|
||||
hdr_radiance = self._apply_gradient_adaptive_dithering(hdr_radiance)
|
||||
|
||||
logger.info(f"Robertson mean radiance: {hdr_radiance.mean():.6f}")
|
||||
|
||||
else: # Default to Debevec - Pure HDR recovery with exposure compensation
|
||||
# Estimate camera response function using Debevec method
|
||||
logger.info("Using Debevec algorithm - Pure HDR mode...")
|
||||
|
||||
# Use higher smoothness for response curve (lambda=50.0)
|
||||
response = self.calibrator.process(processed_images, times)
|
||||
logger.info(f"Response function shape: {response.shape}")
|
||||
|
||||
@@ -433,12 +455,6 @@ class DebevecHDRProcessor:
|
||||
|
||||
logger.info(f"Debevec raw output: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
|
||||
|
||||
# Anti-banding filter
|
||||
if debevec_anti_banding:
|
||||
logger.info("Applying anti-banding bilateral filter...")
|
||||
hdr_radiance = self._apply_antibanding_filter(hdr_radiance)
|
||||
logger.info(f"After anti-banding: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
|
||||
|
||||
# Apply exposure compensation
|
||||
if debevec_exposure_compensation != 0.0:
|
||||
compensation_factor = 2.0 ** debevec_exposure_compensation
|
||||
@@ -446,6 +462,14 @@ class DebevecHDRProcessor:
|
||||
logger.info(f"Applied exposure compensation: {debevec_exposure_compensation:+.1f} stops (factor: {compensation_factor:.6f}x)")
|
||||
logger.info(f"Debevec compensated output: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
|
||||
|
||||
# Optional gradient-adaptive dithering (controlled by debevec_anti_banding parameter)
|
||||
# ONLY apply if user enables it - default relies on lambda=100 smoothness alone
|
||||
if debevec_anti_banding:
|
||||
logger.info("Applying optional gradient-adaptive dithering...")
|
||||
hdr_radiance = self._apply_gradient_adaptive_dithering(hdr_radiance)
|
||||
else:
|
||||
logger.info("Dithering disabled - relying on ultra-smooth response curve (lambda=100) only")
|
||||
|
||||
logger.info(f"Debevec mean radiance: {hdr_radiance.mean():.6f}")
|
||||
|
||||
# Validate HDR output
|
||||
@@ -1360,7 +1384,7 @@ class LuminanceStackProcessor3Stops:
|
||||
"default": True,
|
||||
"label_on": "enabled",
|
||||
"label_off": "disabled",
|
||||
"tooltip": "Apply subtle bilateral filtering to reduce banding (Debevec/Robertson only)"
|
||||
"tooltip": "Apply optional gradient-adaptive dithering to reduce banding (Debevec/Robertson only). Disable for pure lambda=100 smoothness with no color changes."
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -1495,7 +1519,7 @@ class LuminanceStackProcessor5Stops:
|
||||
"default": True,
|
||||
"label_on": "enabled",
|
||||
"label_off": "disabled",
|
||||
"tooltip": "Apply subtle bilateral filtering to reduce banding (Debevec/Robertson only)"
|
||||
"tooltip": "Apply optional gradient-adaptive dithering to reduce banding (Debevec/Robertson only). Disable for pure lambda=100 smoothness with no color changes."
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user