Add ImageFilter module

This commit is contained in:
Nourepide
2023-06-07 05:59:04 +03:00
parent 569c822c4a
commit c11c2aeb1e
5 changed files with 558 additions and 2 deletions
+14
View File
@@ -2,6 +2,7 @@ import json
import os
import folder_paths
import nodes
class Loader:
@@ -31,6 +32,15 @@ class Loader:
if not os.path.exists(fonts_folder_path):
os.mkdir(fonts_folder_path)
def setup_override(self):
if self.config()["override"]["postprocessing"]:
nodes.NODE_CLASS_MAPPINGS = dict(
filter(
lambda item: not item[1].CATEGORY.startswith("image/postprocessing"),
nodes.NODE_CLASS_MAPPINGS.items()
)
)
def get_modules(self):
modules = dict()
@@ -54,6 +64,10 @@ class Loader:
from .modules import ImageDraw
modules.update(ImageDraw.NODE_CLASS_MAPPINGS)
if self.config()["modules"]["ImageFilter"]:
from .modules import ImageFilter
modules.update(ImageFilter.NODE_CLASS_MAPPINGS)
if self.config()["modules"]["ImageSegmentation"]:
from .modules import ImageSegmentation
modules.update(ImageSegmentation.NODE_CLASS_MAPPINGS)
+133 -2
View File
@@ -479,6 +479,136 @@ You also can change the fonts folder in config.
</details>
---
### Image Filter
![image_filter](images/image_filter.png)
> Apply filter on images.
<details>
<summary>Nodes:</summary>
`Warning` Some changes are difficult to notice without detailed consideration.You can load this [JSON](images/image_filter.json) and look at the changes in detail.
### Smooth
![image_draw_polygon](images/image_filter_smooth.png)
> Anti-Aliasing of image artifacts.
### SmoothMore
![image_filter_smooth_more](images/image_filter_smooth_more.png)
> Improved Anti-Aliasing of image artifacts.
### Blur
![image_filter_blur](images/image_filter_blur.png)
> Blurring the image.
### BoxBlur
![image_filter_box_blur](images/image_filter_box_blur.png)
> Blurring the image by box algorithm.
<details>
<summary>Params:</summary>
* radius `[0 - *]` - blurring radius.
</details>
### GaussianBlur
![image_filter_gaussian_blur](images/image_filter_gaussian_blur.png)
> Blurring the image by gaussian algorithm.
<details>
<summary>Params:</summary>
* radius `[0 - *]` - blurring radius.
</details>
### Contour
![image_filter_contour](images/image_filter_contour.png)
> Find the contours of the image.
### Detail
![image_filter_detail](images/image_filter_detail.png)
> Image detailing.
### EdgeEnhance
![image_filter_edge_enhance](images/image_filter_edge_enhance.png)
> Clarity of the image boundaries.
### EdgeEnhanceMore
![image_filter_edge_enhance_more](images/image_filter_edge_enhance_more.png)
> Improved clarity of image boundaries.
### Emboss
![image_filter_emboss](images/image_filter_emboss.png)
> Embossed image.
### FindEdges
![image_filter_find_edges](images/image_filter_find_edges.png)
> Identifies the boundaries of the image.
### Sharpen
![image_filter_sharpen](images/image_filter_sharpen.png)
> Sharpness improvement.
### Rank
![image_filter_rank](images/image_filter_rank.png)
> Rank filter sorts all pixels in a window of a given size.
<details>
<summary>Params:</summary>
* size `[0 - *]` - The size of the core in PX.
* rank `[0 - *]` - Which pixel value to choose.
</details>
### Median
![image_filter_median](images/image_filter_median.png)
> Selects the average pixel value in a window of the specified size.
<details>
<summary>Params:</summary>
* size `[0 - *]` - The size of the core in PX.
</details>
### Min
![image_filter_min](images/image_filter_min.png)
> Selects the smallest pixel value in the window at the specified size.
<details>
<summary>Params:</summary>
* size `[0 - *]` - The size of the core in PX.
</details>
### Max
![image_filter_max](images/image_filter_max.png)
> Selects the largest pixel value in the window at the specified size.
<details>
<summary>Params:</summary>
* size `[0 - *]` - The size of the core in PX.
</details>
### Mode
![image_filter_mode](images/image_filter_mode.png)
> Selects the most common pixel value in a field of the specified size.
<details>
<summary>Params:</summary>
* size `[0 - *]` - The size of the core in PX.
</details>
</details>
---
### Clamp
![clamp](images/clamp.png)
@@ -507,8 +637,9 @@ You also can change the fonts folder in config.
## Configuration:
You can configurate Allor with `config.json`.
* `fonts_folder_path` - Array with a relative path to fonts folder, by default is `["comfy_extras", "fonts"]`. (Converted to `ComfyUI/comfy_extras/fonts` for Unix and `ComfyUI\comfy_extras\fonts` for Windows).
* `modules` - You can disable (or enable) modules at will. Nodes from disabled modules will not be loaded during the start of ComfyUI.
* fonts_folder_path - Array with a relative path to fonts folder, by default is `["comfy_extras", "fonts"]`. (Converted to `ComfyUI/comfy_extras/fonts` for Unix and `ComfyUI\comfy_extras\fonts` for Windows).
* modules - You can disable (or enable) modules at will. Nodes from disabled modules will not be loaded during the start of ComfyUI.
* override - If the nested value is set to `true`, similar functionality from the original nodes is disabled.
## Examples:
![example](images/example.png)
+1
View File
@@ -5,5 +5,6 @@ loader = Loader()
loader.setup_rembg()
loader.setup_paths()
loader.setup_override()
NODE_CLASS_MAPPINGS = loader.get_modules()
+4
View File
@@ -6,7 +6,11 @@
"ImageComposite": true,
"ImageContainer": true,
"ImageDraw": true,
"ImageFilter": true,
"ImageSegmentation": true,
"ImageText": true
},
"override" : {
"postprocessing": true
}
}
+406
View File
@@ -0,0 +1,406 @@
import torch
from PIL import ImageFilter
def applyImageFilter(images, image_filter):
return (torch.stack([
images[i].tensor_to_image().filter(image_filter).image_to_tensor() for i in range(len(images))
]),)
class ImageFilterSmooth:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_smooth"
CATEGORY = "image/filter"
def image_filter_smooth(self, images):
return applyImageFilter(images, ImageFilter.SMOOTH)
class ImageFilterSmoothMore:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_smooth_more"
CATEGORY = "image/filter"
def image_filter_smooth_more(self, images):
return applyImageFilter(images, ImageFilter.SMOOTH_MORE)
class ImageFilterBlur:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_blur"
CATEGORY = "image/filter"
def image_filter_blur(self, images):
return applyImageFilter(images, ImageFilter.BLUR)
class ImageFilterBoxBlur:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"radius": ("INT", {
"default": 1,
"step": 1
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_box_blur"
CATEGORY = "image/filter"
def image_filter_box_blur(self, images, radius):
return applyImageFilter(images, ImageFilter.BoxBlur(radius))
class ImageFilterGaussianBlur:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"radius": ("INT", {
"default": 1,
"step": 1
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_gaussian_blur"
CATEGORY = "image/filter"
def image_filter_gaussian_blur(self, images, radius):
return applyImageFilter(images, ImageFilter.GaussianBlur(radius))
class ImageFilterContour:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_contour"
CATEGORY = "image/filter"
def image_filter_contour(self, images):
return applyImageFilter(images, ImageFilter.CONTOUR)
class ImageFilterDetail:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_detail"
CATEGORY = "image/filter"
def image_filter_detail(self, images):
return applyImageFilter(images, ImageFilter.DETAIL)
class ImageFilterEdgeEnhance:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_edge_enhance"
CATEGORY = "image/filter"
def image_filter_edge_enhance(self, images):
return applyImageFilter(images, ImageFilter.EDGE_ENHANCE)
class ImageFilterEdgeEnhanceMore:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_edge_enhance_more"
CATEGORY = "image/filter"
def image_filter_edge_enhance_more(self, images):
return applyImageFilter(images, ImageFilter.EDGE_ENHANCE_MORE)
class ImageFilterEmboss:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_emboss"
CATEGORY = "image/filter"
def image_filter_emboss(self, images):
return applyImageFilter(images, ImageFilter.EMBOSS)
class ImageFilterFindEdges:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_find_edges"
CATEGORY = "image/filter"
def image_filter_find_edges(self, images):
return applyImageFilter(images, ImageFilter.FIND_EDGES)
class ImageFilterSharpen:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_sharpen"
CATEGORY = "image/filter"
def image_filter_sharpen(self, images):
return applyImageFilter(images, ImageFilter.SHARPEN)
class ImageFilterRank:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"size": ("INT", {
"default": 2,
"min": 0,
"step": 2
}),
"rank": ("INT", {
"default": 1,
"step": 1
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_rank"
CATEGORY = "image/filter"
def image_filter_rank(self, images, size, rank):
return applyImageFilter(images, ImageFilter.RankFilter(int(size) + 1, rank))
class ImageFilterMedian:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"size": ("INT", {
"default": 2,
"min": 0,
"step": 2
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_median"
CATEGORY = "image/filter"
def image_filter_median(self, images, size):
return applyImageFilter(images, ImageFilter.MedianFilter(int(size) + 1))
class ImageFilterMin:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"size": ("INT", {
"default": 2,
"min": 0,
"step": 2
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_min"
CATEGORY = "image/filter"
def image_filter_min(self, images, size):
return applyImageFilter(images, ImageFilter.MinFilter(int(size) + 1))
class ImageFilterMax:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"size": ("INT", {
"default": 2,
"min": 0,
"step": 2
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_max"
CATEGORY = "image/filter"
def image_filter_max(self, images, size):
return applyImageFilter(images, ImageFilter.MaxFilter(int(size) + 1))
class ImageFilterMode:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"size": ("INT", {
"default": 2,
"min": 0,
"step": 2
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "image_filter_mode"
CATEGORY = "image/filter"
def image_filter_mode(self, images, size):
return applyImageFilter(images, ImageFilter.ModeFilter(int(size) + 1))
NODE_CLASS_MAPPINGS = {
"ImageFilterSmooth": ImageFilterSmooth,
"ImageFilterSmoothMore": ImageFilterSmoothMore,
"ImageFilterBlur": ImageFilterBlur,
"ImageFilterBoxBlur": ImageFilterBoxBlur,
"ImageFilterGaussianBlur": ImageFilterGaussianBlur,
"ImageFilterContour": ImageFilterContour,
"ImageFilterDetail": ImageFilterDetail,
"ImageFilterEdgeEnhance": ImageFilterEdgeEnhance,
"ImageFilterEdgeEnhanceMore": ImageFilterEdgeEnhanceMore,
"ImageFilterEmboss": ImageFilterEmboss,
"ImageFilterFindEdges": ImageFilterFindEdges,
"ImageFilterSharpen": ImageFilterSharpen,
"ImageFilterRank": ImageFilterRank,
"ImageFilterMedian": ImageFilterMedian,
"ImageFilterMin": ImageFilterMin,
"ImageFilterMax": ImageFilterMax,
"ImageFilterMode": ImageFilterMode
}