global lancosz

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2025-02-10 11:24:05 -05:00
parent 6270fd829c
commit 640aff898c
16 changed files with 214 additions and 65 deletions
+4 -4
View File
@@ -36,7 +36,7 @@ def HWC3(x):
def make_noise_disk(H, W, C, F):
noise = np.random.uniform(low=0, high=1, size=((H // F) + 2, (W // F) + 2, C))
noise = cv2.resize(noise, (W + 2 * F, H + 2 * F), interpolation=cv2.INTER_CUBIC)
noise = cv2.resize(noise, (W + 2 * F, H + 2 * F), interpolation=cv2.INTER_LANCZOS4)
noise = noise[F: F + H, F: F + W]
noise -= np.min(noise)
noise /= np.max(noise)
@@ -77,7 +77,7 @@ def img2mask(img, H, W, low=10, high=90):
y = img[:, :, random.randrange(0, img.shape[2])]
else:
y = img
y = cv2.resize(y, (W, H), interpolation=cv2.INTER_CUBIC)
y = cv2.resize(y, (W, H), interpolation=cv2.INTER_LANCZOS4)
if random.uniform(0, 1) < 0.5:
y = 255 - y
return y < np.percentile(y, random.randrange(low, high))
@@ -92,7 +92,7 @@ def resize_image(input_image, resolution):
W *= k
H = int(np.round(H / 64.0)) * 64
W = int(np.round(W / 64.0)) * 64
img = cv2.resize(input_image, (W, H), interpolation=cv2.INTER_LANCZOS4 if k > 1 else cv2.INTER_AREA)
img = cv2.resize(input_image, (W, H), interpolation=cv2.INTER_LANCZOS4)
return img
@@ -150,7 +150,7 @@ def blend(images):
y = np.zeros((images[0].shape[0], images[0].shape[1], 3), dtype=np.float32)
for img in images:
if img.shape[0] != y.shape[0] or img.shape[1] != y.shape[1]:
img = cv2.resize(img, (y.shape[1], y.shape[0]), interpolation=cv2.INTER_CUBIC)
img = cv2.resize(img, (y.shape[1], y.shape[0]), interpolation=cv2.INTER_LANCZOS4)
if len(img.shape) == 3 and img.shape[2] == 4: # rgba to rgb
img = cv2.cvtColor(img, cv2.COLOR_RGBA2RGB)
if len(img.shape) == 2: # grayscale to rgb
+2
View File
@@ -315,6 +315,8 @@ def interrogate(question, image, model_name):
image.thumbnail((768, 768), Image.Resampling.HAMMING)
if image.mode != 'RGB':
image = image.convert('RGB')
from modules import modelloader
modelloader.hf_login()
try:
if model_name is None:
shared.log.error(f'Interrogate: type=vlm model="{model_name}" no model selected')
+2 -2
View File
@@ -38,7 +38,7 @@ def prepare_img_and_mask(image, mask, device, pad_out_to_modulo=8, scale_factor=
mode="symmetric",
)
def scale_image(img, factor, interpolation=cv2.INTER_AREA):
def scale_image(img, factor, interpolation=cv2.INTER_LANCZOS4):
if img.shape[0] == 1:
img = img[0]
else:
@@ -54,7 +54,7 @@ def prepare_img_and_mask(image, mask, device, pad_out_to_modulo=8, scale_factor=
out_mask = get_image(mask)
if scale_factor is not None:
out_image = scale_image(out_image, scale_factor)
out_mask = scale_image(out_mask, scale_factor, interpolation=cv2.INTER_NEAREST)
out_mask = scale_image(out_mask, scale_factor, interpolation=cv2.INTER_LANCZOS4)
if pad_out_to_modulo is not None and pad_out_to_modulo > 1:
out_image = pad_img_to_modulo(out_image, pad_out_to_modulo)
out_mask = pad_img_to_modulo(out_mask, pad_out_to_modulo)
+1 -1
View File
@@ -272,7 +272,7 @@ class TransparentVAEDecoder(AutoencoderKL):
B, H, W, C = fg.shape
cb = checkerboard(shape=(H // 64, W // 64))
cb = cv2.resize(cb, (W, H), interpolation=cv2.INTER_NEAREST)
cb = cv2.resize(cb, (W, H), interpolation=cv2.INTER_LANCZOS4)
cb = (0.5 + (cb - 0.5) * 0.1)[None, ..., None]
cb = torch.from_numpy(cb).to(fg)
+3 -3
View File
@@ -238,7 +238,7 @@ def run_segment(input_image: gr.Image, input_mask: np.ndarray):
overlap = 0
if input_mask_size > 0:
if mask.shape != input_mask.shape:
mask = cv2.resize(mask, (input_mask.shape[1], input_mask.shape[0]), interpolation=cv2.INTER_CUBIC)
mask = cv2.resize(mask, (input_mask.shape[1], input_mask.shape[0]), interpolation=cv2.INTER_LANCZOS4)
overlap = cv2.bitwise_and(mask, input_mask)
overlap = np.count_nonzero(overlap)
if overlap == 0:
@@ -278,7 +278,7 @@ def run_rembg(input_image: Image, input_mask: np.ndarray):
binary_input = cv2.threshold(input_mask, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
binary_output = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
if binary_input.shape != binary_output.shape:
binary_output = cv2.resize(binary_output, binary_input.shape[:2], interpolation=cv2.INTER_LINEAR)
binary_output = cv2.resize(binary_output, binary_input.shape[:2], interpolation=cv2.INTER_LANCZOS4)
binary_overlap = cv2.bitwise_and(binary_input, binary_output)
input_size = np.count_nonzero(binary_input)
overlap_size = np.count_nonzero(binary_overlap)
@@ -419,7 +419,7 @@ def run_mask(input_image: Image.Image, input_mask: Image.Image = None, return_ty
mask = run_rembg(input_image, input_mask)
else:
mask = run_segment(input_image, input_mask)
mask = cv2.resize(mask, (input_image.width, input_image.height), interpolation=cv2.INTER_LINEAR)
mask = cv2.resize(mask, (input_image.width, input_image.height), interpolation=cv2.INTER_LANCZOS4)
debug(f'Mask shape={mask.shape} opts={opts}')
if opts.mask_erode > 0:
+20 -17
View File
@@ -144,24 +144,27 @@ def quant_flux_bnb(checkpoint_info, transformer, text_encoder_2):
def load_quants(kwargs, repo_id, cache_dir, allow_quant):
if not allow_quant:
return kwargs
quant_args = {}
quant_args = model_quant.create_bnb_config(quant_args)
if quant_args:
model_quant.load_bnb(f'Load model: type=FLUX quant={quant_args}')
if not quant_args:
quant_args = model_quant.create_ao_config(quant_args)
try:
if not allow_quant:
return kwargs
quant_args = {}
quant_args = model_quant.create_bnb_config(quant_args)
if quant_args:
model_quant.load_torchao(f'Load model: type=FLUX quant={quant_args}')
if not quant_args:
return kwargs
if 'transformer' not in kwargs and ('Model' in shared.opts.bnb_quantization or 'Model' in shared.opts.torchao_quantization):
kwargs['transformer'] = diffusers.FluxTransformer2DModel.from_pretrained(repo_id, subfolder="transformer", cache_dir=cache_dir, torch_dtype=devices.dtype, **quant_args)
shared.log.debug(f'Quantization: module=transformer type=bnb dtype={shared.opts.bnb_quantization_type} storage={shared.opts.bnb_quantization_storage}')
if 'text_encoder_2' not in kwargs and ('Text Encoder' in shared.opts.bnb_quantization or 'Text Encoder' in shared.opts.torchao_quantization):
kwargs['text_encoder_2'] = transformers.T5EncoderModel.from_pretrained(repo_id, subfolder="text_encoder_2", cache_dir=cache_dir, torch_dtype=devices.dtype, **quant_args)
shared.log.debug(f'Quantization: module=t5 type=bnb dtype={shared.opts.bnb_quantization_type} storage={shared.opts.bnb_quantization_storage}')
model_quant.load_bnb(f'Load model: type=FLUX quant={quant_args}')
if not quant_args:
quant_args = model_quant.create_ao_config(quant_args)
if quant_args:
model_quant.load_torchao(f'Load model: type=FLUX quant={quant_args}')
if not quant_args:
return kwargs
if 'transformer' not in kwargs and ('Model' in shared.opts.bnb_quantization or 'Model' in shared.opts.torchao_quantization):
kwargs['transformer'] = diffusers.FluxTransformer2DModel.from_pretrained(repo_id, subfolder="transformer", cache_dir=cache_dir, torch_dtype=devices.dtype, **quant_args)
shared.log.debug(f'Quantization: module=transformer type=bnb dtype={shared.opts.bnb_quantization_type} storage={shared.opts.bnb_quantization_storage}')
if 'text_encoder_2' not in kwargs and ('Text Encoder' in shared.opts.bnb_quantization or 'Text Encoder' in shared.opts.torchao_quantization):
kwargs['text_encoder_2'] = transformers.T5EncoderModel.from_pretrained(repo_id, subfolder="text_encoder_2", cache_dir=cache_dir, torch_dtype=devices.dtype, **quant_args)
shared.log.debug(f'Quantization: module=t5 type=bnb dtype={shared.opts.bnb_quantization_type} storage={shared.opts.bnb_quantization_storage}')
except Exception as e:
shared.log.error(f'Quantization: {e}')
return kwargs
+5 -5
View File
@@ -45,12 +45,12 @@ def center_crop_arr(pil_image, image_size):
"""
while min(*pil_image.size) >= 2 * image_size:
pil_image = pil_image.resize(
tuple(x // 2 for x in pil_image.size), resample=Image.BOX
tuple(x // 2 for x in pil_image.size), resample=Image.Resampling.LANCZOS
)
scale = image_size / min(*pil_image.size)
pil_image = pil_image.resize(
tuple(round(x * scale) for x in pil_image.size), resample=Image.BICUBIC
tuple(round(x * scale) for x in pil_image.size), resample=Image.Resampling.LANCZOS
)
arr = np.array(pil_image)
@@ -63,19 +63,19 @@ def center_crop_arr(pil_image, image_size):
def crop_arr(pil_image, max_image_size):
while min(*pil_image.size) >= 2 * max_image_size:
pil_image = pil_image.resize(
tuple(x // 2 for x in pil_image.size), resample=Image.BOX
tuple(x // 2 for x in pil_image.size), resample=Image.Resampling.LANCZOS
)
if max(*pil_image.size) > max_image_size:
scale = max_image_size / max(*pil_image.size)
pil_image = pil_image.resize(
tuple(round(x * scale) for x in pil_image.size), resample=Image.BICUBIC
tuple(round(x * scale) for x in pil_image.size), resample=Image.Resampling.LANCZOS
)
if min(*pil_image.size) < 16:
scale = 16 / min(*pil_image.size)
pil_image = pil_image.resize(
tuple(round(x * scale) for x in pil_image.size), resample=Image.BICUBIC
tuple(round(x * scale) for x in pil_image.size), resample=Image.Resampling.LANCZOS
)
arr = np.array(pil_image)
+1 -1
View File
@@ -103,7 +103,7 @@ def setup_model(dirname):
restored_img = self.face_helper.paste_faces_to_input_image()
restored_img = restored_img[:, :, ::-1]
if original_resolution != restored_img.shape[0:2]:
restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1]/restored_img.shape[1], fy=original_resolution[0]/restored_img.shape[0], interpolation=cv2.INTER_LINEAR)
restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1]/restored_img.shape[1], fy=original_resolution[0]/restored_img.shape[0], interpolation=cv2.INTER_LANCZOS4)
self.face_helper.clean_all()
if shared.opts.detailer_unload:
self.send_model_to(devices.cpu)
+127
View File
@@ -0,0 +1,127 @@
import numpy as np
def DetectDirect(A, type, k, T):
if type == 1:
# 45 degree diagonal direction
t1 = abs(A[2,0]-A[0,2])
t2 = abs(A[4,0]-A[2,2])+abs(A[2,2]-A[0,4])
t3 = abs(A[6,0]-A[4,2])+abs(A[4,2]-A[2,4])+abs(A[2,4]-A[0,6])
t4 = abs(A[6,2]-A[4,4])+abs(A[4,4]-A[2,6])
t5 = abs(A[6,4]-A[4,6])
d1 = t1+t2+t3+t4+t5
# 135 degree diagonal direction
t1 = abs(A[0,4]-A[2,6])
t2 = abs(A[0,2]-A[2,4])+abs(A[2,4]-A[4,6])
t3 = abs(A[0,0]-A[2,2])+abs(A[2,2]-A[4,4])+abs(A[4,4]-A[6,6])
t4 = abs(A[2,0]-A[4,2])+abs(A[4,2]-A[6,4])
t5 = abs(A[4,0]-A[6,2])
d2 = t1+t2+t3+t4+t5
else:
# horizontal direction
t1 = abs(A[0,1]-A[0,3])+abs(A[2,1]-A[2,3])+abs(A[4,1]-A[4,3])
t2 = abs(A[1,0]-A[1,2])+abs(A[1,2]-A[1,4])
t3 = abs(A[3,0]-A[3,2])+abs(A[3,2]-A[3,4])
d1 = t1+t2+t3
# vertical direction
t1 = abs(A[1,0]-A[3,0])+abs(A[1,2]-A[3,2])+abs(A[1,4]-A[3,4])
t2 = abs(A[0,1]-A[2,1])+abs(A[2,1]-A[4,1])
t3 = abs(A[0,3]-A[2,3])+abs(A[2,3]-A[4,3])
d2 = t1+t2+t3
# Compute the weight vector
w = np.array([1/(1+d1**k), 1/(1+d2**k)])
# Compute the directional index
n = 3
if (1+d1)/(1+d2) > T:
n = 1
elif (1+d2)/(1+d1) > T:
n = 2
return w, n
def PixelValue(A, mode, w, n, f):
if mode == 1:
v1 = np.diag(np.fliplr(A))[::2]
v2 = np.diag(A)[::2]
else:
v1 = A[3,::2]
v2 = A[::2,3]
if n == 1:
p = np.dot(v2, f)
elif n == 2:
p = np.dot(v1, f)
else:
p1 = np.dot(v1, f)
p2 = np.dot(v2, f)
p = (w[0]*p1+w[1]*p2)/(w[0]+w[1])
return p
def PadLeftTop(img_pad, H, W):
img = img_pad[3:-3,3:-3]
# Pad the first/last three col and row
img_pad[3:H+3,1]=img[:,0]
img_pad[H+3::2,3:W+3]=img[H-2:H-1,:]
img_pad[3:H+3,W+3::2]=img[:,W-2:W-1]
img_pad[1,3:W+3]=img[0,:]
# Pad the missing nine points
img_pad[1,1]=img[0,0]
img_pad[H+3::2,1]=img[H-2,0]
img_pad[H+3::2,W+3::2]=img[H-2,W-2]
img_pad[1,W+3::2]=img[0,W-2]
return img_pad
def PadRightBottom(img_pad, H, W):
img = img_pad[3:-3,3:-3]
# Pad the first/last three col and row
img_pad[3:H+3,0:3:2]=img[:,1:2]
img_pad[H+4::2,3:W+3]=img[H-1:H,:]
img_pad[3:H+3,W+4::2]=img[:,W-1:W]
img_pad[0:3:2,3:W+3]=img[1,:]
# Pad the missing nine points
img_pad[0:3:2,0:3:2]=img[1,1]
img_pad[H+4,0:3:2]=img[H-1,1]
img_pad[H+4,W+4]=img[H-1,W-1]
img_pad[0:3:2,W+4]=img[0,W-1]
return img_pad
def _DCC(I, k, T):
m, n = I.shape
nRow = 2*m
nCol = 2*n
A = np.zeros([nRow+6, nCol+6])
A[0+3:-1-3:2, 0+3:-1-3:2] = I
A = PadLeftTop(A, nRow, nCol)
f = np.array([-1, 9, 9, -1])/16
for i in range(4,nRow+3,2):
for j in range(4,nCol+3,2):
[w,n] = DetectDirect(A[i-3:i+4,j-3:j+4],1,k,T)
A[i,j] = PixelValue(A[i-3:i+4,j-3:j+4],1,w,n,f)
A = PadRightBottom(A, nRow, nCol)
for i in range(3,nRow+3,2):
for j in range(4,nCol+3,2):
[w,n] = DetectDirect(A[i-2:i+3,j-2:j+3],2,k,T)
A[i,j] = PixelValue(A[i-3:i+4,j-3:j+4],2,w,n,f)
for i in range(4,nRow+3,2):
for j in range(3,nCol+3,2):
[w,n] = DetectDirect(A[i-2:i+3,j-2:j+3],3,k,T)
A[i,j] = PixelValue(A[i-3:i+4,j-3:j+4],3,w,n,f)
return A[3:-3,3:-3]
'''
img: Shape[H,W,C], Value Range[0-1]
level: super resolution level
Return: super resolution img who shape is the same with input
'''
def DCC(img, level):
# hyper parameters
k, T = 5, 1.15
sr_img = img
# get the high resolution image channel by channel
for channel in range(img.shape[-1]):
sr_img_simple = img[:,:,channel]
for _ in range(level):
sr_img_simple = _DCC(sr_img_simple, k, T)
sr_img[:,:,channel] = sr_img_simple
return sr_img
+1 -1
View File
@@ -253,7 +253,7 @@ class RealESRGANer():
output_alpha = cv2.cvtColor(output_alpha, cv2.COLOR_BGR2GRAY)
else: # use the cv2 resize for alpha channel
h, w = alpha.shape[0:2]
output_alpha = cv2.resize(alpha, (w * self.scale, h * self.scale), interpolation=cv2.INTER_LINEAR)
output_alpha = cv2.resize(alpha, (w * self.scale, h * self.scale), interpolation=cv2.INTER_LANCZOS4)
# merge the alpha channel
output_img = cv2.cvtColor(output_img, cv2.COLOR_BGR2BGRA)
+2 -2
View File
@@ -34,7 +34,7 @@ def restore(np_image, name, session, strength): # pylint: disable=unused-argumen
detected_faces = len(face_helper.cropped_faces)
for cropped_face in face_helper.cropped_faces:
cropped_face = cv2.resize(cropped_face, resolution, interpolation=cv2.INTER_LINEAR)
cropped_face = cv2.resize(cropped_face, resolution, interpolation=cv2.INTER_LANCZOS4)
cropped_face = cropped_face.astype(np.float16)[:,:,::-1] / 255.0
cropped_face = cropped_face.transpose((2, 0, 1))
cropped_face = (cropped_face - 0.5) / 0.5
@@ -52,7 +52,7 @@ def restore(np_image, name, session, strength): # pylint: disable=unused-argumen
restored_img = face_helper.paste_faces_to_input_image()
restored_img = restored_img[:, :, ::-1]
if original_resolution != restored_img.shape[0:2]:
restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1]/restored_img.shape[1], fy=original_resolution[0]/restored_img.shape[0], interpolation=cv2.INTER_LINEAR)
restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1]/restored_img.shape[1], fy=original_resolution[0]/restored_img.shape[0], interpolation=cv2.INTER_LANCZOS4)
face_helper.clean_all()
t1 = time.time()
+1 -1
View File
@@ -1,4 +1,4 @@
from typing import Optional, Sequence, Tuple
from typing import Optional, Tuple
import torch
import torch.nn as nn
+1 -1
View File
@@ -113,7 +113,7 @@ class Upscaler:
if img.width >= dest_w and img.height >= dest_h:
break
if img.width != dest_w or img.height != dest_h:
img = img.resize((int(dest_w), int(dest_h)), resample=Image.Resampling.BICUBIC)
img = img.resize((int(dest_w), int(dest_h)), resample=Image.Resampling.LANCZOS)
shared.state.end()
shared.state = orig_state
return img
+22
View File
@@ -119,3 +119,25 @@ class UpscalerAsymmetricVAE(Upscaler):
upscaled = F.to_pil_image(tensor.squeeze().clamp(0.0, 1.0).float().cpu())
self.vae = self.vae.to(device=devices.cpu)
return upscaled
class UpscalerDCC(Upscaler):
def __init__(self, dirname=None): # pylint: disable=unused-argument
super().__init__(False)
self.name = "DCC Interpolation"
self.vae = None
self.scalers = [
UpscalerData("DCC Interpolation", None, self),
]
def do_upscale(self, img: Image, selected_model=None):
import math
import numpy as np
from modules.postprocess.dcc import DCC
normalized = np.array(img).astype(np.float32) / 255.0
scale = math.ceil(self.scale)
upscaled = DCC(normalized, scale)
upscaled = (upscaled - upscaled.min()) / (upscaled.max() - upscaled.min())
upscaled = (255.0 * upscaled).astype(np.uint8)
upscaled = Image.fromarray(upscaled)
return upscaled