commit HDR Effect node
This commit is contained in:
@@ -70,6 +70,7 @@ When this error has occurred, please check the network environment.
|
||||
## Update
|
||||
<font size="4">**If the dependency package error after updating, please reinstall the relevant dependency packages. for details, please refer to [here](https://github.com/chflame163/ComfyUI_LayerStyle/issues/5). </font><br />
|
||||
|
||||
* Commit [HDR Effect](#HDR) node,it enhances the dynamic range and visual appeal of input images. this node is repackage of [HDR Effects (SuperBeasts.AI)](https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts).
|
||||
* Commit [CropBoxResolve](#CropBoxResolve) node.
|
||||
* Commit [BiRefNetUltra](#BiRefNetUltra) node, it using the BiRefNet model to remove background has better recognition ability and ultra-high edge details.
|
||||
* Commit [ImageAutoCropV2](#ImageAutoCropV2) node, it can choose not to remove the background, support mask input, and scale by long or short side size.
|
||||
@@ -1246,6 +1247,22 @@ Node options:
|
||||
* angle: Angle of channel separation.
|
||||
* mode: Channel shift arrangement order.
|
||||
|
||||
|
||||
### <a id="table1">HDR</a> Effects
|
||||
enhances the dynamic range and visual appeal of input images.
|
||||
This node is reorganize and encapsulate of [HDR Effects (SuperBeasts.AI)](https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts), thanks to the original author.
|
||||

|
||||
|
||||
Node options:
|
||||

|
||||
* hdr_intensity: Range: 0.0 to 5.0, Controls the overall intensity of the HDR effect, Higher values result in a more pronounced HDR effect.
|
||||
* shadow_intensity: Range: 0.0 to 1.0,Adjusts the intensity of shadows in the image,Higher values darken the shadows and increase contrast.
|
||||
* highlight_intensity: Range: 0.0 to 1.0,Adjusts the intensity of highlights in the image,Higher values brighten the highlights and increase contrast.
|
||||
* gamma_intensity: Range: 0.0 to 1.0,Controls the gamma correction applied to the image,Higher values increase the overall brightness and contrast.
|
||||
* contrast: Range: 0.0 to 1.0,Enhances the contrast of the image, Higher values result in more pronounced contrast.
|
||||
* enhance_color: Range: 0.0 to 1.0,Enhances the color saturation of the image, Higher values result in more vibrant colors.
|
||||
|
||||
|
||||
### <a id="table1">Film</a>
|
||||
Simulate the grain, dark edge, and blurred edge of the film, support input depth map to simulate defocus.
|
||||
This node is reorganize and encapsulate of [digitaljohn/comfyui-propost](https://github.com/digitaljohn/comfyui-propost), thanks to the original author.
|
||||
|
||||
+17
-1
@@ -70,7 +70,7 @@ git clone https://github.com/chflame163/ComfyUI_LayerStyle.git
|
||||
## 更新说明
|
||||
<font size="4">**如果本插件更新后出现依赖包错误,请重新安装相关依赖包。
|
||||
|
||||
|
||||
* 添加 [HDR Effect](#HDR) 节点,增强图片动态范围。这个节点是[HDR Effects (SuperBeasts.AI)](https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts)的重新封装。感谢原作者。
|
||||
* 添加 [CropBoxResolve](#CropBoxResolve) 节点。
|
||||
* 添加 [BiRefNetUltra](#BiRefNetUltra) 节点, 使用BiRefNet模型去除背景,有更好的识别能力,同时具有超高的边缘细节。
|
||||
* 添加 [ImageAutoCropV2](#ImageAutoCropV2) 节点,可选择不去除背景,支持mask输入,支持按长边或短边尺寸缩放。
|
||||
@@ -1245,6 +1245,22 @@ mask反转
|
||||
* angle: 通道分离的角度。
|
||||
* mode: 通道错位排列顺序。
|
||||
|
||||
*
|
||||
### <a id="table1">HDR</a> Effects
|
||||
增强图像的动态范围。
|
||||
这个节点是[HDR Effects (SuperBeasts.AI)](https://github.com/SuperBeastsAI/ComfyUI-SuperBeasts)的重新封装。感谢原作者。
|
||||

|
||||
|
||||
节点选项说明:
|
||||

|
||||
* hdr_intensity: 范围0-5, 控制HDR效果的整体强度, 数值越高,效果越明显。
|
||||
* shadow_intensity: 范围0-1,调整图像阴影部分的强度,较高的值会使阴影变暗并增加对比度。
|
||||
* highlight_intensity: 范围0-1,调整图像高光部分的强度,较高的值可使高光变亮并增加对比度。
|
||||
* gamma_intensity: 范围0-1,用于图像的伽玛校正,值越高,整体亮度和对比度越高。
|
||||
* contrast: 范围0-1,增强图像的对比度, 值越高,对比度越明显。
|
||||
* enhance_color: 范围0-1,增强图像的色彩饱和度, 值越高,颜色越鲜艳。
|
||||
|
||||
|
||||
### <a id="table1">Film</a>
|
||||
模拟胶片的颗粒、暗边和边缘模糊,支持输入深度图模拟虚焦。
|
||||
这个节点是[digitaljohn/comfyui-propost](https://github.com/digitaljohn/comfyui-propost)的重新封装,感谢原作者。
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
@@ -0,0 +1,162 @@
|
||||
from .imagefunc import *
|
||||
from PIL import ImageCms
|
||||
from PIL.PngImagePlugin import PngInfo
|
||||
|
||||
NODE_NAME = 'HDR Effects'
|
||||
|
||||
sRGB_profile = ImageCms.createProfile("sRGB")
|
||||
Lab_profile = ImageCms.createProfile("LAB")
|
||||
|
||||
def adjust_shadows(luminance_array, shadow_intensity, hdr_intensity):
|
||||
# Darken shadows more as shadow_intensity increases, scaled by hdr_intensity
|
||||
return np.clip(luminance_array - luminance_array * shadow_intensity * hdr_intensity * 0.5, 0, 255)
|
||||
|
||||
|
||||
def adjust_highlights(luminance_array, highlight_intensity, hdr_intensity):
|
||||
# Brighten highlights more as highlight_intensity increases, scaled by hdr_intensity
|
||||
return np.clip(luminance_array + (255 - luminance_array) * highlight_intensity * hdr_intensity * 0.5, 0, 255)
|
||||
|
||||
|
||||
def apply_adjustment(base, factor, intensity_scale):
|
||||
"""Apply positive adjustment scaled by intensity."""
|
||||
# Ensure the adjustment increases values within [0, 1] range, scaling by intensity
|
||||
adjustment = base + (base * factor * intensity_scale)
|
||||
# Ensure adjustment stays within bounds
|
||||
return np.clip(adjustment, 0, 1)
|
||||
|
||||
|
||||
def multiply_blend(base, blend):
|
||||
"""Multiply blend mode."""
|
||||
return np.clip(base * blend, 0, 255)
|
||||
|
||||
|
||||
def overlay_blend(base, blend):
|
||||
"""Overlay blend mode."""
|
||||
# Normalize base and blend to [0, 1] for blending calculation
|
||||
base = base / 255.0
|
||||
blend = blend / 255.0
|
||||
return np.where(base < 0.5, 2 * base * blend, 1 - 2 * (1 - base) * (1 - blend)) * 255
|
||||
|
||||
|
||||
def adjust_shadows_non_linear(luminance, shadow_intensity, max_shadow_adjustment=1.5):
|
||||
lum_array = np.array(luminance, dtype=np.float32) / 255.0 # Normalize
|
||||
# Apply a non-linear darkening effect based on shadow_intensity
|
||||
shadows = lum_array ** (1 / (1 + shadow_intensity * max_shadow_adjustment))
|
||||
return np.clip(shadows * 255, 0, 255).astype(np.uint8) # Re-scale to [0, 255]
|
||||
|
||||
|
||||
def adjust_highlights_non_linear(luminance, highlight_intensity, max_highlight_adjustment=1.5):
|
||||
lum_array = np.array(luminance, dtype=np.float32) / 255.0 # Normalize
|
||||
# Brighten highlights more aggressively based on highlight_intensity
|
||||
highlights = 1 - (1 - lum_array) ** (1 + highlight_intensity * max_highlight_adjustment)
|
||||
return np.clip(highlights * 255, 0, 255).astype(np.uint8) # Re-scale to [0, 255]
|
||||
|
||||
|
||||
def merge_adjustments_with_blend_modes(luminance, shadows, highlights, hdr_intensity, shadow_intensity,
|
||||
highlight_intensity):
|
||||
# Ensure the data is in the correct format for processing
|
||||
base = np.array(luminance, dtype=np.float32)
|
||||
|
||||
# Scale the adjustments based on hdr_intensity
|
||||
scaled_shadow_intensity = shadow_intensity ** 2 * hdr_intensity
|
||||
scaled_highlight_intensity = highlight_intensity ** 2 * hdr_intensity
|
||||
|
||||
# Create luminance-based masks for shadows and highlights
|
||||
shadow_mask = np.clip((1 - (base / 255)) ** 2, 0, 1)
|
||||
highlight_mask = np.clip((base / 255) ** 2, 0, 1)
|
||||
|
||||
# Apply the adjustments using the masks
|
||||
adjusted_shadows = np.clip(base * (1 - shadow_mask * scaled_shadow_intensity), 0, 255)
|
||||
adjusted_highlights = np.clip(base + (255 - base) * highlight_mask * scaled_highlight_intensity, 0, 255)
|
||||
|
||||
# Combine the adjusted shadows and highlights
|
||||
adjusted_luminance = np.clip(adjusted_shadows + adjusted_highlights - base, 0, 255)
|
||||
|
||||
# Blend the adjusted luminance with the original luminance based on hdr_intensity
|
||||
final_luminance = np.clip(base * (1 - hdr_intensity) + adjusted_luminance * hdr_intensity, 0, 255).astype(np.uint8)
|
||||
|
||||
return Image.fromarray(final_luminance)
|
||||
|
||||
|
||||
def apply_gamma_correction(lum_array, intensity, base_gamma):
|
||||
"""
|
||||
Apply gamma correction to the luminance array.
|
||||
:param lum_array: Luminance channel as a NumPy array.
|
||||
:param intensity: HDR intensity factor.
|
||||
:param base_gamma: Base gamma value for correction.
|
||||
"""
|
||||
if intensity == 0: # If intensity is 0, return the array as is.
|
||||
return lum_array
|
||||
|
||||
gamma = 1 + (base_gamma - 1) * intensity # Scale gamma based on intensity.
|
||||
adjusted = 255 * (lum_array / 255) ** gamma
|
||||
return np.clip(adjusted, 0, 255).astype(np.uint8)
|
||||
|
||||
|
||||
class LS_HDREffects:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {'required': {'image': ('IMAGE', {'default': None}),
|
||||
'hdr_intensity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 5.0, 'step': 0.01}),
|
||||
'shadow_intensity': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}),
|
||||
'highlight_intensity': ('FLOAT', {'default': 0.75, 'min': 0.0, 'max': 1.0, 'step': 0.01}),
|
||||
'gamma_intensity': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}),
|
||||
'contrast': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.01}),
|
||||
'enhance_color': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01})
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ('IMAGE',)
|
||||
RETURN_NAMES = ('image',)
|
||||
FUNCTION = 'hdr_effects'
|
||||
CATEGORY = '😺dzNodes/LayerFilter'
|
||||
|
||||
@apply_to_batch
|
||||
def hdr_effects(self, image, hdr_intensity=0.5, shadow_intensity=0.25, highlight_intensity=0.75,
|
||||
gamma_intensity=0.25, contrast=0.1, enhance_color=0.25):
|
||||
# Load the image
|
||||
img = tensor2pil(image)
|
||||
|
||||
# Step 1: Convert RGB to LAB for better color preservation
|
||||
img_lab = ImageCms.profileToProfile(img, sRGB_profile, Lab_profile, outputMode='LAB')
|
||||
|
||||
# Extract L, A, and B channels
|
||||
luminance, a, b = img_lab.split()
|
||||
|
||||
# Convert luminance to a NumPy array for processing
|
||||
lum_array = np.array(luminance, dtype=np.float32)
|
||||
|
||||
# Preparing adjustment layers (shadows, midtones, highlights)
|
||||
# This example assumes you have methods to extract or calculate these adjustments
|
||||
shadows_adjusted = adjust_shadows_non_linear(luminance, shadow_intensity)
|
||||
highlights_adjusted = adjust_highlights_non_linear(luminance, highlight_intensity)
|
||||
|
||||
merged_adjustments = merge_adjustments_with_blend_modes(lum_array, shadows_adjusted, highlights_adjusted,
|
||||
hdr_intensity, shadow_intensity, highlight_intensity)
|
||||
|
||||
# Apply gamma correction with a base_gamma value (define based on desired effect)
|
||||
gamma_corrected = apply_gamma_correction(np.array(merged_adjustments), hdr_intensity, gamma_intensity)
|
||||
|
||||
# Merge L channel back with original A and B channels
|
||||
adjusted_lab = Image.merge('LAB', (merged_adjustments, a, b))
|
||||
|
||||
# Step 3: Convert LAB back to RGB
|
||||
img_adjusted = ImageCms.profileToProfile(adjusted_lab, Lab_profile, sRGB_profile, outputMode='RGB')
|
||||
|
||||
# Enhance contrast
|
||||
enhancer = ImageEnhance.Contrast(img_adjusted)
|
||||
contrast_adjusted = enhancer.enhance(1 + contrast)
|
||||
|
||||
# Enhance color saturation
|
||||
enhancer = ImageEnhance.Color(contrast_adjusted)
|
||||
color_adjusted = enhancer.enhance(1 + enhance_color * 0.2)
|
||||
|
||||
return pil2tensor(color_adjusted)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"LayerFilter: HDREffects": LS_HDREffects
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"LayerFilter: HDREffects": "LayerFilter: HDR Effects"
|
||||
}
|
||||
@@ -53,6 +53,20 @@ except ImportError as e:
|
||||
f"\nFor detail refer to \033[4mhttps://github.com/chflame163/ComfyUI_LayerStyle/issues/5\033[0m")
|
||||
|
||||
|
||||
|
||||
'''warpper'''
|
||||
|
||||
# create a wrapper function that can apply a function to multiple images in a batch while passing all other arguments to the function
|
||||
def apply_to_batch(func):
|
||||
def wrapper(self, image, *args, **kwargs):
|
||||
images = []
|
||||
for img in image:
|
||||
images.append(func(self, img, *args, **kwargs))
|
||||
batch_tensor = torch.cat(images, dim=0)
|
||||
return (batch_tensor,)
|
||||
return wrapper
|
||||
|
||||
|
||||
'''pickle'''
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user