Add new filters

pull/20/head
LEv145 2023-06-20 17:15:03 +02:00
parent 5069e2b2ba
commit 90a1452e3f
7 changed files with 179 additions and 57 deletions

49
hakuimg/color.py → hakuimg/color/__init__.py Normal file → Executable file
View File

@ -2,23 +2,50 @@ from PIL import Image, ImageEnhance
import cv2
import numpy as np
from .exposure_offset import get_exposure_offset
from .hdr import get_hdr
from .noise import get_noise
from .sharpness import get_sharpness
from .vignette import get_vignette
def run(img1, bright, contrast, sat, temp, hue, gamma):
def run(
img1,
bright,
contrast,
sat,
temp,
hue,
gamma,
exposure_offset,
hdr,
noise,
sharpness,
vignette,
):
bright /=100
contrast /=100
temp /=100
sat /=100
#brigtness
res = Image.fromarray(img1)
res = get_exposure_offset(res, exposure_offset, bright)
res = get_hdr(res, hdr, img1)
res = get_sharpness(res, sharpness)
res = get_noise(res, noise)
res = get_vignette(res, vignette)
#brigtness
#res = Image.fromarray(res)
brightness = ImageEnhance.Brightness(res)
res = brightness.enhance(1+bright)
#contrast
cont = ImageEnhance.Contrast(res)
res = cont.enhance(1+contrast)
res = np.array(res).astype(np.float32)
#temp
if temp>0:
res[:, :, 0] *= 1+temp
@ -26,23 +53,23 @@ def run(img1, bright, contrast, sat, temp, hue, gamma):
elif temp<0:
res[:, :, 2] *= 1-temp
res = np.clip(res, 0, 255)/255
res = np.clip(np.power(res, gamma), 0, 1)
#saturation
print(res.shape)
sat_real = 1 + sat
hls_img = cv2.cvtColor(res, cv2.COLOR_RGB2HLS)
hls_img[:, :, 2] = np.clip(sat_real*hls_img[:, :, 2], 0, 1)
res = cv2.cvtColor(hls_img, cv2.COLOR_HLS2RGB)*255
# hue
hsv_img = cv2.cvtColor(res, cv2.COLOR_RGB2HSV)
print(np.max(hsv_img[:, :, 0]), np.max(hsv_img[:, :, 1]), np.max(hsv_img[:, :, 2]))
hsv_img[:, :, 0] = (hsv_img[:, :, 0]+hue)%360
res = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)
res = res.astype(np.uint8)
res = Image.fromarray(res, mode='RGB')
return res
return res

View File

@ -0,0 +1,14 @@
from PIL import ImageEnhance, Image
import numpy as np
def get_exposure_offset(img, value, brightness_value):
if value <= 0:
return img
np_img = np.array(img).astype(float) + value * 75
np_img = np.clip(np_img, 0, 255).astype(np.uint8)
img = Image.fromarray(np_img)
return ImageEnhance.Brightness(img).enhance(
(brightness_value+1) - value / 4
)

36
hakuimg/color/hdr.py Executable file
View File

@ -0,0 +1,36 @@
import cv2
import numpy as np
from PIL import ImageFilter, ImageChops, Image, ImageOps, ImageEnhance
from blendmodes.blend import blendLayers, BlendType
def get_hdr(img, value, original_img):
if value <= 0:
return img
blurred = img.filter(ImageFilter.GaussianBlur(radius=2.8))
difference = ImageChops.difference(img, blurred)
sharp_edges = Image.blend(img, difference, 1)
converted_original_img = (
np.array(original_img)[:, :, ::-1].copy().astype("float32") / 255.0
)
converted_sharped = (
np.array(sharp_edges)[:, :, ::-1].copy().astype("float32") / 255.0
)
color_dodge = converted_original_img / (1 - converted_sharped)
converted_color_dodge = (255 * color_dodge).clip(0, 255).astype(np.uint8)
temp_img = Image.fromarray(
cv2.cvtColor(converted_color_dodge, cv2.COLOR_BGR2RGB)
)
inverted_color_dodge = ImageOps.invert(temp_img)
black_white_color_dodge = ImageEnhance.Color(inverted_color_dodge).enhance(0)
hue = blendLayers(temp_img, black_white_color_dodge, BlendType.HUE)
hdrImage = blendLayers(hue, temp_img, BlendType.NORMAL, 0.7)
return blendLayers(img, hdrImage, BlendType.NORMAL, value * 2).convert(
"RGB"
)

12
hakuimg/color/noise.py Executable file
View File

@ -0,0 +1,12 @@
from PIL import ImageChops, Image
import numpy as np
def get_noise(img, value):
if value <= 0:
return img
noise = np.random.randint(0, value * 100, img.size, np.uint8)
noise_img = Image.fromarray(noise, 'L').resize(img.size).convert(img.mode)
return ImageChops.add(img, noise_img)

8
hakuimg/color/sharpness.py Executable file
View File

@ -0,0 +1,8 @@
from PIL import ImageEnhance
def get_sharpness(img, value):
if value <= 0:
return img
return ImageEnhance.Sharpness(img).enhance((value+1) * 1.5)

16
hakuimg/color/vignette.py Executable file
View File

@ -0,0 +1,16 @@
from PIL import ImageDraw, Image, ImageFilter
def get_vignette(img, value):
if value <= 0:
return img
width, height = img.size
mask = Image.new("L", (width, height), 0)
draw = ImageDraw.Draw(mask)
padding = 100 - value * 100
draw.ellipse(
(-padding, -padding, width + padding, height + padding), fill=255
)
mask = mask.filter(ImageFilter.GaussianBlur(radius=100))
return Image.composite(img, Image.new("RGB", img.size, "black"), mask)

101
scripts/main.py Normal file → Executable file
View File

@ -44,14 +44,14 @@ class Script(scripts.Script):
if isinstance(component, gr.Gallery):
if component.elem_id in {'txt2img_gallery', 'img2img_gallery'}:
img_src = component
val = kwargs.get("value", "")
id = kwargs.get("elem_id", "")
if id=='img_inpaint_base':
inpaint_base = component
if id=='img_inpaint_mask':
inpaint_mask = component
if id=='extras_tab':
with gr.Accordion('HakuImg', open=False):
with gr.Column():
@ -64,9 +64,9 @@ class Script(scripts.Script):
with gr.Column():
btn3 = gr.Button("Send to Effect")
btn3.click(None, _js=f"switch_to_haku_img_eff")
all_btns.append((btns, btn3, img_src))
def ui(self, is_img2img):
return []
@ -104,7 +104,7 @@ def add_tab():
)
bg_color = gr.ColorPicker('#FFFFFF', label='background color')
expand_btn = gr.Button("refresh", variant="primary")
with gr.TabItem('Effect', elem_id='haku_eff'):
img_eff_h_slider = gr.Slider(160, 1280, 320, step=10, label="Image preview height", elem_id='haku_img_h_eff')
image_eff = gr.Image(type='numpy', label="img", elem_id='haku_img_eff', show_label=False)
@ -119,10 +119,18 @@ def add_tab():
with gr.Row():
sat_slider = gr.Slider(-100, 100, 0, step=1, label="saturation")
gamma_slider = gr.Slider(0.2, 2.2, 1, step=0.1, label="Gamma")
with gr.Row():
exposure_offset_slider = gr.Slider(0, 1, 0, label="ExposureOffset")
vignette_slider = gr.Slider(0, 1, 0, label="Vignette")
with gr.Row():
noise_slider = gr.Slider(0, 1, 0, label="Noise")
sharpness_slider = gr.Slider(0, 1, 0, label="Sharpness")
with gr.Row():
hdr_slider = gr.Slider(0, 1, 0, label="HDR")
with gr.Row():
color_btn = gr.Button("refresh", variant="primary")
color_rst_btn = gr.Button("reset")
with gr.TabItem('Tone Curve', elem_id='haku_curve'):
all_points = [[], [], [], []]
all_curve_defaults = [[], [], [], []]
@ -134,11 +142,11 @@ def add_tab():
with gr.Row():
all_points[index] += [
gr.Slider(
0, 255, int(255*i/(points+1)),
0, 255, int(255*i/(points+1)),
step=1, label=f'point{i} x'
),
gr.Slider(
0, 255, int(255*i/(points+1)),
0, 255, int(255*i/(points+1)),
step=1, label=f'point{i} y'
)
]
@ -147,41 +155,41 @@ def add_tab():
with gr.Row():
curve_btn = gr.Button("refresh", variant="primary")
curve_rst_btn = gr.Button("reset")
with gr.TabItem('Blur', elem_id='haku_blur'):
blur_slider = gr.Slider(0, 128, 8, label="blur")
blur_btn = gr.Button("refresh", variant="primary")
with gr.TabItem('Sketch', elem_id='haku_sketch'):
sk_kernel = gr.Slider(0, 25, 0, step=1, label='kernel size')
with gr.Row():
sk_sigma = gr.Slider(1, 5, 1.4, step=0.05, label='sigma')
sk_k_sigma = gr.Slider(1, 5, 1.6, step=0.05, label='k_sigma')
with gr.Row():
sk_eps = gr.Slider(-0.2, 0.2, -0.03, step=0.005, label='epsilon')
sk_phi = gr.Slider(1, 50, 10, step=1, label='phi')
sk_gamma = gr.Slider(0.75, 1, 1, step=0.005, label='gamma')
sk_color = gr.Radio(['gray', 'rgb'], value='gray', label='color mode')
sk_scale = gr.Checkbox(False, label='use scale')
with gr.Row():
sketch_btn = gr.Button("refresh", variant="primary")
sketch_rst_btn = gr.Button("reset")
with gr.TabItem('Pixelize', elem_id='haku_Pixelize'):
p_colors = gr.Slider(2, 256, 128, step=1, label='colors')
p_dot_size = gr.Slider(1, 32, 6, step=1, label='dot size')
p_outline = gr.Slider(0, 10, 1, step=1, label='outline inflating')
p_smooth = gr.Slider(0, 10, 4, step=1, label='Smoothing')
p_mode = gr.Radio(
['kmeans', 'dithering', 'kmeans with dithering'],
['kmeans', 'dithering', 'kmeans with dithering'],
value='kmeans', label='Color reduce algo'
)
with gr.Row():
pixel_btn = gr.Button("refresh", variant="primary")
pixel_rst_btn = gr.Button("reset")
with gr.TabItem('Glow', elem_id='haku_Glow'):
neon_mode = gr.Radio(['BS', 'BMBL'], value='BS', label='Glow mode')
neon_blur = gr.Slider(2, 128, 16, step=1, label='range')
@ -189,7 +197,7 @@ def add_tab():
with gr.Row():
neon_btn = gr.Button("refresh", variant="primary")
neon_rst_btn = gr.Button("reset")
with gr.TabItem('Other'):
img_other_h_slider = gr.Slider(160, 1280, 320, step=10, label="Image preview height", elem_id='haku_img_h_oth')
image_other = gr.Image(type='numpy', label="img", elem_id='haku_img_other', show_label=False)
@ -200,14 +208,14 @@ def add_tab():
iop_l = gr.Slider(0, 512, 0, step=64, label='fill left')
iop_r = gr.Slider(0, 512, 0, step=64, label='fill right')
iop_btn = gr.Button("refresh", variant="primary")
with gr.Column():
img_out_h_slider = gr.Slider(160, 1280, 420, step=10, label="Image preview height", elem_id='haku_img_h_out')
res_info = gr.Textbox(label='Resolution')
image_out = gr.Image(
interactive=False,
type='pil',
label="haku_output",
interactive=False,
type='pil',
label="haku_output",
elem_id='haku_out'
)
image_mask = gr.Image(visible=False)
@ -220,7 +228,7 @@ def add_tab():
for i in range(layers, 0, -1):
send_blends.append(gr.Button(f"Send to Layer{i}", elem_id=f'send_haku_blend{i}'))
send_eff = gr.Button("Send to Effect", elem_id='send_haku_blur')
#preview height slider
img_blend_h_slider.change(None, img_blend_h_slider, _js=f'get_change_height("haku_img_blend")')
img_eff_h_slider.change(None, img_eff_h_slider, _js=f'get_change_height("haku_img_eff")')
@ -228,7 +236,7 @@ def add_tab():
img_out_h_slider.change(None, img_out_h_slider, _js=f'get_change_height("haku_out")')
image_out.change(lambda x:f'{x.width} x {x.height}', image_out, res_info)
image_out.change(None, img_out_h_slider, _js=f'get_change_height("haku_out")')
# blend
all_blend_set = [bg_color]
all_blend_set += all_alphas+all_mask_blur+all_mask_str+all_mode
@ -236,24 +244,25 @@ def add_tab():
for component in all_blend_set:
component.change(blend.run(layers), all_blend_input, image_out)
expand_btn.click(blend.run(layers), all_blend_input, image_out)
#blur
all_blur_input = [image_eff, blur_slider]
blur_slider.change(blur.run, all_blur_input, outputs=image_out)
blur_btn.click(blur.run, all_blur_input, outputs=image_out)
#color
all_color_set = [
bright_slider, contrast_slider, sat_slider,
temp_slider, hue_slider, gamma_slider
bright_slider, contrast_slider, sat_slider,
temp_slider, hue_slider, gamma_slider,
exposure_offset_slider, hdr_slider, noise_slider,
sharpness_slider, vignette_slider
]
all_color_input = [image_eff] + all_color_set
for component in all_color_set:
component.change(color.run, all_color_input, image_out)
color_btn.click(color.run, all_color_input, image_out)
color_rst_btn.click(lambda:[0, 0, 0, 0, 0, 1.0], None, all_color_set)
color_rst_btn.click(lambda:[0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0], None, all_color_set)
#curve
all_curve_set = sum(all_points, start=[])
all_curve_defaults = sum(all_curve_defaults, [])
@ -264,7 +273,7 @@ def add_tab():
curve_btn.click(curve.curve_img, components, all_curves[index])
curve_btn.click(curve.run(points), all_curve_input, image_out)
curve_rst_btn.click(lambda: all_curve_defaults, None, all_curve_set)
#sketch
all_sk_set = [
sk_kernel, sk_sigma, sk_k_sigma, sk_eps, sk_phi, sk_gamma, sk_color, sk_scale
@ -274,7 +283,7 @@ def add_tab():
component.change(sketch.run, all_sk_input, image_out)
sketch_btn.click(sketch.run, all_sk_input, image_out)
sketch_rst_btn.click(lambda: [0, 1.4, 1.6, -0.03, 10, 1, 'gray', False], None, all_sk_set)
#pixelize
all_p_set = [
p_colors, p_dot_size, p_smooth, p_outline, p_mode
@ -284,7 +293,7 @@ def add_tab():
component.change(pixel.run, all_p_input, image_out)
pixel_btn.click(pixel.run, all_p_input, image_out)
pixel_rst_btn.click(lambda: [16, 8, 0, 5, 'kmeans'], None, all_p_set)
#neon
all_neon_set = [
neon_blur, neon_str, neon_mode,
@ -294,7 +303,7 @@ def add_tab():
component.change(neon.run, all_neon_input, image_out)
neon_btn.click(neon.run, all_neon_input, image_out)
neon_rst_btn.click(lambda: [16, 1, 'BS'], None, all_neon_set)
#iop
all_iop_set = [
iop_u, iop_d, iop_l, iop_r
@ -303,50 +312,50 @@ def add_tab():
for component in all_iop_set:
component.change(outpaint.run, all_iop_input, [image_out, image_mask])
iop_btn.click(outpaint.run, all_iop_input, [image_out, image_mask])
#send
for btns, btn3, img_src in all_btns:
for btn, img in zip(btns, all_layers):
btn.click(gpc.image_from_url_text, img_src, img, _js="extract_image_from_gallery")
btn3.click(gpc.image_from_url_text, img_src, image_eff, _js="extract_image_from_gallery")
gpc.bind_buttons(send_btns, image_out, None)
for btn, img in zip(btns, all_layers):
btn.click(lambda x:x, image_out, img)
btn.click(None, _js = 'switch_to_haku_blend')
for layer, send_btn in zip(all_layers, send_blends):
send_btn.click(lambda x:x, image_out, layer)
send_btn.click(None, _js='switch_to_haku_blend')
send_ip_b.click(lambda *x:x, [image_out, image_mask], [inpaint_base, inpaint_mask])
send_ip_b.click(None, _js = 'switch_to_inpaint_upload')
send_eff.click(lambda x:x, image_out, image_eff)
send_eff.click(None, _js = 'switch_to_haku_eff')
return (demo , "HakuImg", "haku_img"),
def on_ui_settings():
section = ('haku-img', "HakuImg")
shared.opts.add_option(
"hakuimg_layer_num",
"hakuimg_layer_num",
shared.OptionInfo(
5,
"Total num of layers (reload required)",
5,
"Total num of layers (reload required)",
section=section
)
)
shared.opts.add_option(
"hakuimg_curve_points",
"hakuimg_curve_points",
shared.OptionInfo(
3,
"Total num of point for curve (reload required)",
3,
"Total num of point for curve (reload required)",
section=section
)
)
script_callbacks.on_ui_tabs(add_tab)
script_callbacks.on_ui_settings(on_ui_settings)
script_callbacks.on_ui_settings(on_ui_settings)