Add Pixelize

pull/21/head
Kohaku-Blueleaf 2023-01-20 01:28:23 +08:00
parent 616cb6c677
commit 680e7d00d2
5 changed files with 213 additions and 10 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__/

183
hakuimg/pixel.py Normal file
View File

@ -0,0 +1,183 @@
from typing import Any
from numpy.typing import NDArray
import cv2
from PIL import Image
import numpy as np
INFLATE_FILTER = [
None,
np.array(
[[0, 1, 0],
[1, 1, 1],
[0, 1, 0]], np.uint8
),
np.array(
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], np.uint8
),
np.array(
[[0, 0, 1, 0, 0],
[0, 1, 1, 1, 0],
[1, 1, 1, 1, 1],
[0, 1, 1, 1, 0],
[0, 0, 1, 0, 0]], np.uint8
),
np.array(
[[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]], np.uint8
),
np.ones((7, 7), np.uint8),
np.ones((9, 9), np.uint8),
np.ones((11, 11), np.uint8),
np.ones((13, 13), np.uint8),
np.ones((15, 15), np.uint8),
np.ones((17, 17), np.uint8)
]
def read_img_as_array(
img
) -> NDArray[Any]:
'''Convert image to RGBA and read to ndarray'''
img = Image.fromarray(img)
img = img.convert('RGBA')
img_arr = np.asarray(img)
return img_arr
def preprocess(
img: NDArray[Any],
blur: int = 0,
erode: int = 0,
) -> NDArray[Any]:
'''
Process for
* outline inflation (erode)
* smoothing (blur)
* saturation
* contrast
'''
# outline process
if erode:
img = cv2.erode(
img, INFLATE_FILTER[erode],
iterations = 1,
)
# blur process
if blur:
img = cv2.bilateralFilter(
img, 15, blur*20, 20
)
img = img.astype(np.float32)
return img
def pixelize(
img: NDArray[Any],
k: int, c: int,
d_w: int, d_h: int,
o_w: int, o_h: int,
precise: int,
) -> tuple[NDArray[Any], NDArray[Any]]:
'''
Use down scale and up scale to make pixel image.
And use k-means to confine the num of colors.
'''
img = cv2.resize(
img, (d_w, d_h),
interpolation = cv2.INTER_NEAREST
)
# reshape to 1-dim array(for every color) for k-means
# use k-means to abstract the colors to use
img_cp = img.reshape(-1, c)
criteria = (
cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,
precise*5, 0.01
)
_, label, center = cv2.kmeans(
img_cp, k, None,
criteria, 1, cv2.KMEANS_PP_CENTERS
)
result = center[label.flatten()]
result = result.reshape((img.shape))
result = cv2.resize(
result,
(o_w, o_h),
interpolation=cv2.INTER_NEAREST
)
return result.astype(np.uint8), center.astype(np.uint8)
def run(
src: Image.Image,
k: int = 3,
scale: int = 2,
blur: int = 0,
erode: int = 0,
precise: int = 10,
) -> tuple[Image.Image, list[list[str|float]]]:
#print('Start process.')
#print('Read raw image... ', end='', flush=True)
img = read_img_as_array(src)
#convert color space
alpha_channel = img[:, :, 3]
img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGB)
h, w, c = img.shape
d_h = h // scale
d_w = w // scale
o_h = d_h * scale
o_w = d_w * scale
#print('done!')
#print('Image preprocess... ', end='', flush=True)
# preprocess(erode, blur, saturation, contrast)
img = preprocess(
img,
blur, erode
)
#print('done!')
#print('Pixelize... ', end='', flush=True)
# pixelize(using k-means)
result, colors = pixelize(
img, k, c,
d_w, d_h,
o_w, o_h,
precise
)
#print('done!')
#print('Process output image... ', end='', flush=True)
# add alpha channel
a = cv2.resize(
alpha_channel, (d_w, d_h),
interpolation = cv2.INTER_NEAREST
)
a = cv2.resize(
a, (o_w, o_h),
interpolation = cv2.INTER_NEAREST
)
a[a!=0]=255
if 0 not in a:
a[0, 0] = 0
r, g, b = cv2.split(result)
result = cv2.merge((r, g, b, a))
# for saving to png
result = cv2.cvtColor(
result, cv2.COLOR_RGBA2BGRA
)
#print('done!')
return Image.fromarray(result)

View File

@ -65,3 +65,9 @@ function switch_to_haku_blend(){
function switch_to_haku_eff(){
return switch_to_inner_tab('haku_eff')
}
function switch_to_inpaint_upload(){
switch_to_img2img_tab(4);
return args_to_array(arguments);
}

View File

@ -19,9 +19,3 @@ function get_change_height(id){
id = "div[id*='" + id + "']"
return (height)=>{change_img_height(id, height)}
}
function switch_to_inpaint_upload(){
switch_to_img2img_tab(4);
return args_to_array(arguments);
}

View File

@ -9,10 +9,13 @@ from PIL import Image, ImageFilter, ImageEnhance, ImageColor
import cv2
import numpy as np
from hakuimg import blend
from hakuimg import color
from hakuimg import blur
from hakuimg import sketch
from hakuimg import(
blend,
blur,
color,
sketch,
pixel
)
'''
@ -121,6 +124,13 @@ def add_tab():
sk_scale = gr.Checkbox(False, label='use scale')
sketch_btn = gr.Button("refresh", variant="primary")
with gr.TabItem('Pixelize', elem_id='haku_Pixelize'):
p_colors = gr.Slider(2, 128, 16, step=1, label='colors')
p_dot_size = gr.Slider(2, 32, 8, step=1, label='dot size')
p_outline = gr.Slider(0, 10, 5, step=1, label='outline inflating')
p_smooth = gr.Slider(0, 10, 0, step=1, label='Smoothing')
pixel_btn = gr.Button("refresh", variant="primary")
with gr.TabItem('Other'):
with gr.Tabs(elem_id='function list'):
with gr.TabItem('InOutPaint'):
@ -178,6 +188,15 @@ def add_tab():
component.change(sketch.run, all_sk_input, image_out)
sketch_btn.click(sketch.run, all_sk_input, image_out)
#pixelize
all_p_set = [
p_colors, p_dot_size, p_smooth, p_outline
]
all_p_input = [image_eff] + all_p_set
for component in all_p_set:
component.change(pixel.run, all_p_input, image_out)
pixel_btn.click(pixel.run, all_p_input, image_out)
#send
for btns, btn3, img_src in all_btns:
for btn, img in zip(btns, all_layers):