Add ImageEffectsLensBokeh node.
This commit is contained in:
@@ -595,6 +595,27 @@ You also can change the fonts folder in config.
|
||||
|
||||
</details>
|
||||
|
||||
### Lens Bokeh
|
||||

|
||||
> Emulate a [bokeh](https://en.wikipedia.org/wiki/Bokeh) effect to images.
|
||||
|
||||
<details>
|
||||
<summary>Params:</summary>
|
||||
|
||||
* blades_shape `[3 - *]` - The number of blades at the lens.
|
||||
* blades_radius `[1 - *]` - Size of blades.
|
||||
* blades_rotation `[0.0 - 360.0]` - Blades rotation.
|
||||
* blur_size `[2 - *]` - Blur strength.
|
||||
* blur_type `[bilateral, stack, none]`
|
||||
* **bilateral** - Blur is set up to preserve sharp and bright edges.
|
||||
* **stack** - Blur with color correction.
|
||||
* **none** - Without blur.
|
||||
* method `[dilate, filter]`
|
||||
* **dilate** - A good choice for initially bright images. Creates a strong bokeh effect, but spoils the details of the image. I can recommend it only for the background.
|
||||
* **filter** - Very fast. A weak bokeh effect, I recommend it for dark images with bright rare details such as lamp lights or car headlights. Originally created under the impression of LensBlur in Adobe Photoshop and achieved about 80%~ compliance. I recommend setting `blur_type` as `none` since it blurs the image by itself.
|
||||
|
||||
</details>
|
||||
|
||||
### Lens Optic Axis
|
||||

|
||||
> Apply a camera lens distort to the images.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import cv2
|
||||
import torch
|
||||
import torchvision.transforms.functional as F
|
||||
import numpy as np
|
||||
|
||||
from .Utils import radialspace_1D, radialspace_2D, cv2_layer
|
||||
|
||||
@@ -361,6 +362,90 @@ class ImageEffectsLensChromaticAberration:
|
||||
]),)
|
||||
|
||||
|
||||
class ImageEffectsLensBokeh:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"images": ("IMAGE",),
|
||||
"blades_shape": ("INT", {
|
||||
"default": 5,
|
||||
"min": 3,
|
||||
}),
|
||||
"blades_radius": ("INT", {
|
||||
"default": 10,
|
||||
"min": 1,
|
||||
}),
|
||||
"blades_rotation": ("FLOAT", {
|
||||
"default": 0.0,
|
||||
"min": 0.0,
|
||||
"max": 360.0,
|
||||
}),
|
||||
"blur_size": ("INT", {
|
||||
"default": 10,
|
||||
"min": 1,
|
||||
"step": 2
|
||||
}),
|
||||
"blur_type": (["bilateral", "stack", "none"],),
|
||||
"method": (["dilate", "filter"],),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "node"
|
||||
CATEGORY = "image/effects/lens"
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def lens_blur(self, image, blades_shape, blades_radius, blades_rotation, method):
|
||||
angles = np.linspace(0, 2 * np.pi, blades_shape + 1)[:-1] + blades_rotation * np.pi / 180
|
||||
x = blades_radius * np.cos(angles) + blades_radius
|
||||
y = blades_radius * np.sin(angles) + blades_radius
|
||||
pts = np.stack([x, y], axis=1).astype(np.int32)
|
||||
|
||||
mask = np.zeros((blades_radius * 2 + 1, blades_radius * 2 + 1), np.uint8)
|
||||
cv2.fillPoly(mask, [pts], 255)
|
||||
|
||||
gaussian_kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
|
||||
|
||||
if method == "dilate":
|
||||
kernel = cv2.filter2D(mask, -1, gaussian_kernel)
|
||||
result = cv2.dilate(image, kernel)
|
||||
elif method == "filter":
|
||||
height, width = image.shape[:2]
|
||||
dilate_size = min(height, width) // 512
|
||||
|
||||
if dilate_size > 0:
|
||||
image = cv2.dilate(image, np.ones((dilate_size, dilate_size), np.uint8))
|
||||
|
||||
kernel = mask.astype(np.float32) / np.sum(mask)
|
||||
kernel = cv2.filter2D(kernel, -1, gaussian_kernel)
|
||||
result = cv2.filter2D(image, -1, kernel)
|
||||
else:
|
||||
raise ValueError("Unsupported method.")
|
||||
|
||||
return result
|
||||
|
||||
def node(self, images, blades_shape, blades_radius, blades_rotation, blur_size, blur_type, method):
|
||||
tensor = images.clone().detach()
|
||||
blur_size -= 1
|
||||
|
||||
if blur_type == "bilateral":
|
||||
tensor = cv2_layer(tensor, lambda x: cv2.bilateralFilter(x, blur_size, -100, 100))
|
||||
elif blur_type == "stack":
|
||||
tensor = cv2_layer(tensor, lambda x: cv2.stackBlur(x, (blur_size, blur_size)))
|
||||
elif blur_type == "none":
|
||||
pass
|
||||
else:
|
||||
raise ValueError("Unsupported blur type.")
|
||||
|
||||
return (cv2_layer(tensor, lambda x: self.lens_blur(
|
||||
x, blades_shape, blades_radius, blades_rotation, method)
|
||||
),)
|
||||
|
||||
|
||||
class ImageEffectsLensOpticAxis:
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -528,6 +613,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"ImageEffectsNegative": ImageEffectsNegative,
|
||||
"ImageEffectsSepia": ImageEffectsSepia,
|
||||
"ImageEffectsLensChromaticAberration": ImageEffectsLensChromaticAberration,
|
||||
"ImageEffectsLensBokeh": ImageEffectsLensBokeh,
|
||||
"ImageEffectsLensOpticAxis": ImageEffectsLensOpticAxis,
|
||||
"ImageEffectsLensVignette": ImageEffectsLensVignette
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user