diff --git a/core/imagelib/__init__.py b/core/imagelib/__init__.py index 1ed95dc..c7fb90b 100644 --- a/core/imagelib/__init__.py +++ b/core/imagelib/__init__.py @@ -18,7 +18,7 @@ from .common import random_crop, normalize_channels, cut_odd_image, overlay_alph from .SegIEPolys import * -from .blursharpen import LinearMotionBlur, blursharpen +from .blursharpen import LinearMotionBlur, blursharpen, gaussian_sharpen, unsharpen_mask from .filters import apply_random_rgb_levels, \ apply_random_overlay_triangle, \ diff --git a/core/imagelib/blursharpen.py b/core/imagelib/blursharpen.py index 5174511..79ebdab 100644 --- a/core/imagelib/blursharpen.py +++ b/core/imagelib/blursharpen.py @@ -35,4 +35,18 @@ def blursharpen (img, sharpen_mode=0, kernel_size=3, amount=100): n = max(n-10,0) return img + return img + +def gaussian_sharpen(img, amount=100, sigma=1.0): + img = cv2.addWeighted(img, 1.0 + (0.05 * amount), cv2.GaussianBlur(img, (0, 0), sigma), -(0.05 * amount), 0) + return np.clip(img, 0, 1, out=img) + +def unsharpen_mask(img, amount=100, sigma=0.0, threshold = (5.0 / 255.0)): + radius = max(1, round(img.shape[0] * (amount / 100))) + kernel_size = int((radius * 2) + 1) + kernel_size = (kernel_size, kernel_size) + blur = cv2.GaussianBlur(img, kernel_size, sigma) + low_contrast_mask = (abs(img - blur) < threshold).astype("float32") + sharpened = (img * (1.0 + (0.05 * amount))) + (blur * -(0.05 * amount)) + img = (img * (1.0 - low_contrast_mask)) + (sharpened * low_contrast_mask) return img \ No newline at end of file diff --git a/merger/InteractiveMergerSubprocessor.py b/merger/InteractiveMergerSubprocessor.py index d31349f..b9cb903 100644 --- a/merger/InteractiveMergerSubprocessor.py +++ b/merger/InteractiveMergerSubprocessor.py @@ -330,11 +330,12 @@ class InteractiveMergerSubprocessor(Subprocessor): 'z' : lambda cfg,shift_pressed: cfg.toggle_masked_hist_match(), 'x' : lambda cfg,shift_pressed: cfg.toggle_mask_mode(), 'c' : lambda cfg,shift_pressed: cfg.toggle_color_transfer_mode(), - 'n' : lambda cfg,shift_pressed: cfg.toggle_sharpen_mode(), + 'n' : lambda cfg,shift_pressed: cfg.toggle_sharpen_mode_multi(shift_pressed), '9' : lambda cfg,shift_pressed: cfg.add_pre_sharpen_power(1), '8' : lambda cfg,shift_pressed: cfg.add_pre_sharpen_power(-1), '(' : lambda cfg,shift_pressed: cfg.add_morph_power(1), '*' : lambda cfg,shift_pressed: cfg.add_morph_power(-1), + 'b' : lambda cfg,shift_pressed: cfg.toggle_two_pass(), } self.masked_keys = list(self.masked_keys_funcs.keys()) diff --git a/merger/MergeMasked.py b/merger/MergeMasked.py index 8101e02..b088886 100644 --- a/merger/MergeMasked.py +++ b/merger/MergeMasked.py @@ -62,16 +62,29 @@ def MergeMaskedFace (predictor_func, predictor_input_shape, dst_face_mask_a_0 = np.clip(dst_face_mask_a_0, 0, 1) if cfg.pre_sharpen_power != 0: - dst_face_bgr = cv2.addWeighted(dst_face_bgr, 1.0 + (0.05 * cfg.pre_sharpen_power), cv2.GaussianBlur(dst_face_bgr, (0, 0), 1.0), -(0.05 * cfg.pre_sharpen_power), 0) - dst_face_bgr = np.clip(dst_face_bgr, 0, 1, out=dst_face_bgr) + if cfg.pre_sharpen_mode: + dst_face_bgr = imagelib.gaussian_sharpen(dst_face_bgr, amount=cfg.pre_sharpen_power) + else: + dst_face_bgr = imagelib.unsharpen_mask(dst_face_bgr, amount=cfg.pre_sharpen_power) + + #dst_face_bgr = cv2.addWeighted(dst_face_bgr, 1.0 + (0.05 * cfg.pre_sharpen_power), cv2.GaussianBlur(dst_face_bgr, (0, 0), 1.0), -(0.05 * cfg.pre_sharpen_power), 0) + #dst_face_bgr = np.clip(dst_face_bgr, 0, 1, out=dst_face_bgr) predictor_input_bgr = cv2.resize (dst_face_bgr, (input_size,input_size) ) predicted = predictor_func (predictor_input_bgr, func_morph_factor = cfg.morph_power/100.0) if cfg.is_morphable else predictor_func (predictor_input_bgr) + + prd_face_bgr = np.clip (predicted[0], 0, 1.0) prd_face_mask_a_0 = np.clip (predicted[1], 0, 1.0) prd_face_dst_mask_a_0 = np.clip (predicted[2], 0, 1.0) + + if cfg.two_pass: + predicted_2 = predictor_func (prd_face_bgr, func_morph_factor = 1.0) if cfg.is_morphable else predictor_func (prd_face_bgr) + prd_face_bgr = np.clip (predicted_2[0], 0, 1.0) + prd_face_mask_a_0 = np.clip (predicted_2[1], 0, 1.0) + prd_face_dst_mask_a_0 = np.clip (predicted_2[2], 0, 1.0) if cfg.super_resolution_power != 0: prd_face_bgr_enhanced = face_enhancer_func(prd_face_bgr, is_tanh=True, preserve_size=False) diff --git a/merger/MergerConfig.py b/merger/MergerConfig.py index 7719a92..2278edb 100644 --- a/merger/MergerConfig.py +++ b/merger/MergerConfig.py @@ -97,6 +97,9 @@ mask_mode_dict = {0:'full', ctm_dict = { 0: "None", 1:"rct", 2:"lct", 3:"mkl", 4:"mkl-m", 5:"idt", 6:"idt-m", 7:"sot-m", 8:"mix-m" } ctm_str_dict = {None:0, "rct":1, "lct":2, "mkl":3, "mkl-m":4, "idt":5, "idt-m":6, "sot-m":7, "mix-m":8 } +pre_sharpen_dict = {0:'gaussian', 1:'unsharpen_mask'} + + class MergerConfigMasked(MergerConfig): def __init__(self, face_type=FaceType.FULL, @@ -115,6 +118,8 @@ class MergerConfigMasked(MergerConfig): bicubic_degrade_power = 0, color_degrade_power = 0, pre_sharpen_power = 0, + pre_sharpen_mode=0, + two_pass = False, morph_power = 100, is_morphable = False, **kwargs @@ -145,7 +150,9 @@ class MergerConfigMasked(MergerConfig): self.image_denoise_power = image_denoise_power self.bicubic_degrade_power = bicubic_degrade_power self.color_degrade_power = color_degrade_power + self.two_pass = two_pass self.pre_sharpen_power = pre_sharpen_power + self.pre_sharpen_mode = pre_sharpen_mode self.morph_power = morph_power self.is_morphable = is_morphable @@ -158,7 +165,22 @@ class MergerConfigMasked(MergerConfig): def toggle_masked_hist_match(self): if self.mode == 'hist-match': self.masked_hist_match = not self.masked_hist_match - + + def toggle_two_pass(self): + self.two_pass = not self.two_pass + + + def toggle_sharpen_mode_multi(self, pre_sharpen=False): + if pre_sharpen: + self.toggle_sharpen_mode_presharpen() + else: + self.toggle_sharpen_mode() + + def toggle_sharpen_mode_presharpen(self): + a = list( pre_sharpen_dict.keys() ) + self.pre_sharpen_mode = a[ (a.index(self.pre_sharpen_mode)+1) % len(a) ] + + def add_hist_match_threshold(self, diff): if self.mode == 'hist-match' or self.mode == 'seamless-hist-match': self.hist_match_threshold = np.clip ( self.hist_match_threshold+diff , 0, 255) @@ -227,7 +249,8 @@ class MergerConfigMasked(MergerConfig): self.erode_mask_modifier = np.clip ( io.input_int ("Choose erode mask modifier", 0, add_info="-400..400"), -400, 400) self.blur_mask_modifier = np.clip ( io.input_int ("Choose blur mask modifier", 0, add_info="0..400"), 0, 400) self.motion_blur_power = np.clip ( io.input_int ("Choose motion blur power", 0, add_info="0..100"), 0, 100) - + + self.two_pass = io.input_bool("Use two pass mode?", False, help_message="Can enhance results by feeding network output again to network.") self.pre_sharpen_power = np.clip (io.input_int ("Choose pre_sharpen power", 0, help_message="Can enhance results by pre sharping before feeding it to the network.", add_info="0..100" ), 0, 200) if self.is_morphable: @@ -270,6 +293,8 @@ class MergerConfigMasked(MergerConfig): self.bicubic_degrade_power == other.bicubic_degrade_power and \ self.color_degrade_power == other.color_degrade_power and \ self.pre_sharpen_power == other.pre_sharpen_power and \ + self.pre_sharpen_mode == other.pre_sharpen_mode and \ + self.two_pass == other.two_pass and \ self.morph_power == other.morph_power and \ self.is_morphable == other.is_morphable @@ -308,8 +333,10 @@ class MergerConfigMasked(MergerConfig): f"""color_degrade_power: {self.color_degrade_power}\n""") r += f"""pre_sharpen_power: {self.pre_sharpen_power}\n""" + r += f"""pre_sharpen_mode: {pre_sharpen_dict[self.pre_sharpen_mode]}\n""" + r += f"""two_pass: {self.two_pass}\n""" r += f"""morph_power: {self.morph_power}\n""" - r += f"""is_morphable: {self.is_morphable}\n""" + #r += f"""is_morphable: {self.is_morphable}\n""" r += "================"