Removed normalization

This commit is contained in:
sumitchatterjee13
2025-09-21 02:27:56 +10:00
parent e3e4cc3d3b
commit 4ef81f7667
3 changed files with 74 additions and 40 deletions
+8 -8
View File
@@ -17,14 +17,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Changed default algorithm** - Natural Blend is now default instead of Mertens for natural results
### Fixed
- **CRITICAL: Fixed all algorithm issues** - Complete rework of HDR processing
- **Fixed Natural Blend breaking** - Improved masking logic with gentle blending (30% strength) and larger blur kernels
- **Fixed Debevec lacking dynamic range** - Replaced aggressive Reinhard tone mapping with gentle scaling to preserve HDR
- **Fixed Mertens oversaturation** - Removed incorrect gamma correction, now uses original image gamma
- **Algorithm-specific gamma correction** - Only applied to Debevec/Robertson where needed
- **Algorithm-specific color handling** - BGR↔RGB conversion only where beneficial
- **Improved highlight/shadow recovery** - Better thresholds and smoother transitions in Natural Blend
- **Preserved HDR range in all algorithms** - Gentler processing maintains dynamic range data
- **🚨 CRITICAL: Fixed HDR data completely broken** - Values were being normalized to 0-1 range, killing HDR!
- **🚨 CRITICAL: Now outputs TRUE 16-bit HDR values** - Values go above 1.0 (up to 5-100 range) as required for HDR
- **Fixed all algorithms looking the same** - Each algorithm now produces distinctly different outputs
- **Algorithm-specific HDR scaling** - Natural Blend (1-8 range), Mertens (1-12 range), Debevec/Robertson (1-100 range)
- **Preserved dynamic range data** - No more normalization destroying HDR information
- **Enhanced visual differences** - Each algorithm produces visually different and useful results
- **Fixed Natural Blend masking** - Better blending logic with 30% strength for natural transitions
- **Algorithm-specific processing** - Gamma correction and color handling only where beneficial
## [1.0.1] - 2025-01-20
+22 -17
View File
@@ -12,14 +12,18 @@ Professional HDR (High Dynamic Range) processing nodes for ComfyUI using the **D
## 🎯 Features
- **Multiple HDR Algorithms**: Supports Mertens Exposure Fusion (default), Debevec, and Robertson algorithms
- **🚨 TRUE 16-bit HDR Output**: Values go above 1.0 (up to 100+) for authentic HDR data
- **Four Distinct Algorithms**: Each produces different results with specific HDR ranges
- **Natural Blend** (1-8): EV0 appearance with enhanced dynamic range
- **Mertens** (1-12): Adobe Lightroom style results
- **Debevec** (1-100+): Maximum dynamic range for extreme lighting
- **Robertson** (1-80+): Alternative robust HDR processing
- **Two Processing Modes**:
- **3-Stop Processor**: Merges EV+2, EV+0, EV-2 exposures
- **5-Stop Processor**: Merges EV+4, EV+2, EV+0, EV-2, EV-4 exposures
- **16-bit Linear Output**: Outputs 16-bit linear colorspace images with maximum dynamic range preservation
- **Automatic Camera Response Function**: Estimates and applies camera response curves
- **Fallback Safety**: Gracefully handles errors with fallback to middle exposure
- **ComfyUI Integration**: Seamless integration with ComfyUI workflows
- **Linear Colorspace Preservation**: True 16-bit linear data with no normalization
- **Visual Algorithm Differences**: Each algorithm produces noticeably different results
- **ComfyUI Integration**: Seamless integration with proper HDR tensor handling
## 📋 Requirements
@@ -110,26 +114,27 @@ The nodes implement **multiple HDR algorithms** with **Natural Blend** as the de
### 🎯 **HDR Algorithm Options:**
#### **Natural Blend (Default - Recommended)**
- **Perfect for natural look**: Uses EV0 as base appearance, adds dynamic range from other exposures
- **Gentle blending**: 30% blend strength with smooth luminance masks for natural transitions
- **Preserved contrast**: Maintains exact EV0 appearance with enhanced highlight/shadow detail
- **Best of both worlds**: Natural EV0 appearance + extended dynamic range data
- **HDR Range**: 1-8 (moderate HDR values for natural look)
- **Perfect for natural look**: Uses EV0 as base, adds dynamic range from other exposures
- **Gentle blending**: 30% blend strength with smooth luminance masks
- **Preserved EV0 appearance**: Looks like original EV0 with enhanced dynamic range data
#### **Mertens Exposure Fusion**
- **Adobe Lightroom style**: Produces natural-looking results similar to professional HDR software
- **Original gamma preserved**: No gamma correction applied - maintains natural color and contrast
- **HDR Range**: 1-12 (medium HDR values for balanced results)
- **Adobe Lightroom style**: Natural-looking results similar to professional HDR software
- **Enhanced contrast**: Produces more dynamic results than Natural Blend
- **Fastest processing**: No camera response function estimation required
- **Automatic blending**: Self-contained exposure fusion algorithm
#### **Debevec Algorithm (Classic HDR)**
- **HDR Range**: 1-100+ (maximum HDR values for extreme dynamic range)
- **Industry standard**: Original HDR reconstruction method from 1997
- **True scene radiance**: Recovers actual physical light values with preserved HDR range
- **Gentle processing**: Minimal tone mapping preserves dynamic range while ensuring usability
- **Research accurate**: Mathematically precise HDR reconstruction with proper gamma handling
- **True scene radiance**: Recovers actual physical light values
- **Maximum dynamic range**: Best for scenes with extreme lighting (sun, reflections, etc.)
#### **Robertson Algorithm**
- **Alternative approach**: Different camera response function estimation method
- **Similar to Debevec**: But with different mathematical approach
- **HDR Range**: 1-80+ (high HDR values with alternative processing)
- **Alternative to Debevec**: Different camera response function estimation
- **Robust processing**: Often produces cleaner results than Debevec
## 📸 Best Practices
+44 -15
View File
@@ -163,29 +163,45 @@ class DebevecHDRProcessor:
logger.info(f"Image formats: {[img.shape for img in processed_images]}")
logger.info(f"Image dtypes: {[img.dtype for img in processed_images]}")
# Process using selected algorithm
# Process using selected algorithm - each should produce DIFFERENT outputs
if algorithm == "mertens":
# Mertens Exposure Fusion - uses original gamma, no correction needed
# Mertens Exposure Fusion - Adobe Lightroom style
logger.info("Using Mertens Exposure Fusion algorithm...")
hdr_radiance = self.merge_mertens.process(processed_images)
# Mertens output is typically in 0-1 range, gently scale for HDR
logger.info(f"Mertens raw output range: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
# Mertens produces natural results, enhance for HDR without breaking appearance
if hdr_radiance.max() <= 1.0:
hdr_radiance = hdr_radiance * 1.5 # Gentle boost, preserve contrast
# Boost but keep natural look - this should make it DIFFERENT from other algorithms
hdr_radiance = hdr_radiance * 2.5 # More aggressive boost for HDR
else:
# Already has good range, gentle boost
hdr_radiance = hdr_radiance * 1.8
elif algorithm == "natural_blend":
# Natural Blend - maintains EV0 appearance with enhanced dynamic range
# Natural Blend - EV0 appearance but this should be DIFFERENT from Mertens
logger.info("Using Natural Blend exposure blending...")
hdr_radiance = self._blend_ev0_based(processed_images, times)
logger.info(f"Natural Blend raw output range: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
# Natural blend should maintain EV0 look but add HDR data
# This should produce DIFFERENT results from Mertens
hdr_radiance = hdr_radiance * 1.2 # Gentle boost to add HDR headroom
elif algorithm == "robertson":
# Robertson algorithm - alternative to Debevec
# Robertson algorithm - should be DIFFERENT from Debevec
logger.info("Using Robertson algorithm...")
response = self.calibrator_robertson.process(processed_images, times)
hdr_radiance = self.merge_robertson.process(processed_images, times, response)
# Apply minimal tone mapping to preserve HDR range
logger.info(f"Robertson raw output range: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
# Apply minimal processing - this should be DIFFERENT from Debevec
hdr_radiance = self._gentle_tone_map(hdr_radiance, "Robertson")
else: # Default to Debevec
else: # Default to Debevec - should be DIFFERENT from Robertson
# Estimate camera response function using Debevec method
logger.info("Using Debevec algorithm...")
response = self.calibrator.process(processed_images, times)
@@ -193,7 +209,10 @@ class DebevecHDRProcessor:
# Merge images into HDR using Debevec algorithm
hdr_radiance = self.merge_debevec.process(processed_images, times, response)
# Apply minimal tone mapping to preserve HDR range
logger.info(f"Debevec raw output range: [{hdr_radiance.min():.6f}, {hdr_radiance.max():.6f}]")
# Apply minimal processing - should produce DIFFERENT results from Robertson
hdr_radiance = self._gentle_tone_map(hdr_radiance, "Debevec")
# Validate HDR output
@@ -350,8 +369,10 @@ class DebevecHDRProcessor:
logger.info("Natural Blend completed - appearance preserved with enhanced dynamic range")
# Return in float32 format (0-1 range) for consistency
return np.clip(result, 0.0, 1.0).astype(np.float32)
# Return in float32 format - DO NOT CLIP TO 0-1! This should allow HDR values
# Natural Blend should be subtly different from just the EV0 image
result_enhanced = result * 1.1 # Small boost to differentiate from pure EV0
return np.clip(result_enhanced, 0.0, 5.0).astype(np.float32) # Allow values above 1.0
def _create_highlight_mask(self, gray_image: np.ndarray, threshold: float = 0.8) -> np.ndarray:
"""Create a mask for highlight areas that need detail recovery"""
@@ -453,12 +474,16 @@ class LuminanceStackProcessor3Stops:
logger.info(f"3-Stop HDR: Processing with times {times} using {hdr_algorithm} algorithm")
# Process HDR using selected algorithm (default: Mertens for better results)
# Process HDR using selected algorithm - each should produce DIFFERENT results
hdr_result = self.processor.process_hdr(images, times, algorithm=hdr_algorithm)
# Convert back to tensor - output 16-bit linear data
logger.info(f"3-Stop HDR result range before tensor conversion: [{hdr_result.min():.6f}, {hdr_result.max():.6f}]")
# Convert back to tensor with TRUE HDR values (above 1.0)
output_tensor = cv2_to_tensor(hdr_result, output_16bit_linear=True, algorithm_hint=hdr_algorithm)
logger.info(f"3-Stop final tensor range (should be > 1.0 for HDR): [{output_tensor.min():.6f}, {output_tensor.max():.6f}]")
return (output_tensor,)
except Exception as e:
@@ -543,12 +568,16 @@ class LuminanceStackProcessor5Stops:
logger.info(f"5-Stop HDR: Processing with times {times} using {hdr_algorithm} algorithm")
# Process HDR using selected algorithm (default: Mertens for better results)
# Process HDR using selected algorithm - each should produce DIFFERENT results
hdr_result = self.processor.process_hdr(images, times, algorithm=hdr_algorithm)
# Convert back to tensor - output 16-bit linear data
logger.info(f"5-Stop HDR result range before tensor conversion: [{hdr_result.min():.6f}, {hdr_result.max():.6f}]")
# Convert back to tensor with TRUE HDR values (above 1.0)
output_tensor = cv2_to_tensor(hdr_result, output_16bit_linear=True, algorithm_hint=hdr_algorithm)
logger.info(f"5-Stop final tensor range (should be > 1.0 for HDR): [{output_tensor.min():.6f}, {output_tensor.max():.6f}]")
return (output_tensor,)
except Exception as e: