fix outpainting image padding
This commit is contained in:
parent
1571018cfd
commit
b8a030f83a
@ -85,59 +85,44 @@ def image_blur(data, std=3.14, mode="linear"):
|
|||||||
return np.real(convolve(data, kernel / np.sqrt(np.sum(kernel * kernel))))
|
return np.real(convolve(data, kernel / np.sqrt(np.sum(kernel * kernel))))
|
||||||
|
|
||||||
|
|
||||||
def soften_mask(np_rgba_image, softness, space):
|
def soften_mask(mask_img, softness, space):
|
||||||
if softness == 0:
|
if softness == 0:
|
||||||
return np_rgba_image
|
return mask_img
|
||||||
softness = min(softness, 1.0)
|
softness = min(softness, 1.0)
|
||||||
space = np.clip(space, 0.0, 1.0)
|
space = np.clip(space, 0.0, 1.0)
|
||||||
original_max_opacity = np.max(np_rgba_image[:, :, 3])
|
original_max_opacity = np.max(mask_img)
|
||||||
out_mask = np_rgba_image[:, :, 3] <= 0.0
|
out_mask = mask_img <= 0.0
|
||||||
blurred_mask = image_blur(np_rgba_image[:, :, 3], 3.5 / softness, mode="linear")
|
blurred_mask = image_blur(mask_img, 3.5 / softness, mode="linear")
|
||||||
blurred_mask = np.maximum(blurred_mask - np.max(blurred_mask[out_mask]), 0.0)
|
blurred_mask = np.maximum(blurred_mask - np.max(blurred_mask[out_mask]), 0.0)
|
||||||
np_rgba_image[
|
mask_img *= blurred_mask # preserve partial opacity in original input mask
|
||||||
:, :, 3
|
mask_img /= np.max(mask_img) # renormalize
|
||||||
] *= blurred_mask # preserve partial opacity in original input mask
|
mask_img = np.clip(mask_img - space, 0.0, 1.0) # make space
|
||||||
np_rgba_image[:, :, 3] /= np.max(np_rgba_image[:, :, 3]) # renormalize
|
mask_img /= np.max(mask_img) # and renormalize again
|
||||||
np_rgba_image[:, :, 3] = np.clip(
|
mask_img *= original_max_opacity # restore original max opacity
|
||||||
np_rgba_image[:, :, 3] - space, 0.0, 1.0
|
return mask_img
|
||||||
) # make space
|
|
||||||
np_rgba_image[:, :, 3] /= np.max(np_rgba_image[:, :, 3]) # and renormalize again
|
|
||||||
np_rgba_image[:, :, 3] *= original_max_opacity # restore original max opacity
|
|
||||||
return np_rgba_image
|
|
||||||
|
|
||||||
|
|
||||||
def expand_image(
|
def expand_image(
|
||||||
cv2_img, top: int, right: int, bottom: int, left: int, softness: float, space: float
|
cv2_img, top: int, right: int, bottom: int, left: int, softness: float, space: float
|
||||||
):
|
):
|
||||||
|
assert cv2_img.shape[2] == 3
|
||||||
origin_h, origin_w = cv2_img.shape[:2]
|
origin_h, origin_w = cv2_img.shape[:2]
|
||||||
new_width = cv2_img.shape[1] + left + right
|
new_width = cv2_img.shape[1] + left + right
|
||||||
new_height = cv2_img.shape[0] + top + bottom
|
new_height = cv2_img.shape[0] + top + bottom
|
||||||
new_img = np.zeros((new_height, new_width, 4), np.uint8) # expanded image is rgba
|
|
||||||
|
|
||||||
print(
|
# TODO: which is better?
|
||||||
"Expanding input image from {0}x{1} to {2}x{3}".format(
|
# new_img = np.random.randint(0, 255, (new_height, new_width, 3), np.uint8)
|
||||||
cv2_img.shape[1], cv2_img.shape[0], new_width, new_height
|
new_img = cv2.copyMakeBorder(
|
||||||
)
|
cv2_img, top, bottom, left, right, cv2.BORDER_REPLICATE
|
||||||
)
|
|
||||||
if cv2_img.shape[2] == 3: # rgb input image
|
|
||||||
new_img[
|
|
||||||
top : top + cv2_img.shape[0], left : left + cv2_img.shape[1], 0:3
|
|
||||||
] = cv2_img
|
|
||||||
new_img[
|
|
||||||
top : top + cv2_img.shape[0], left : left + cv2_img.shape[1], 3
|
|
||||||
] = 255 # fully opaque
|
|
||||||
elif cv2_img.shape[2] == 4: # rgba input image
|
|
||||||
new_img[top : top + cv2_img.shape[0], left : left + cv2_img.shape[1]] = cv2_img
|
|
||||||
else:
|
|
||||||
raise Exception(
|
|
||||||
"Unsupported image format: {0} channels".format(cv2_img.shape[2])
|
|
||||||
)
|
)
|
||||||
|
mask_img = np.zeros((new_height, new_width), np.uint8)
|
||||||
|
mask_img[top : top + cv2_img.shape[0], left : left + cv2_img.shape[1]] = 255
|
||||||
|
|
||||||
if softness > 0.0:
|
if softness > 0.0:
|
||||||
new_img = soften_mask(new_img / 255.0, softness / 100.0, space / 100.0)
|
mask_img = soften_mask(mask_img / 255.0, softness / 100.0, space / 100.0)
|
||||||
new_img = (np.clip(new_img, 0.0, 1.0) * 255.0).astype(np.uint8)
|
mask_img = (np.clip(mask_img, 0.0, 1.0) * 255.0).astype(np.uint8)
|
||||||
|
|
||||||
mask_image = 255.0 - new_img[:, :, 3] # extract mask from alpha channel and invert
|
mask_image = 255.0 - mask_img # extract mask from alpha channel and invert
|
||||||
rgb_init_image = (
|
rgb_init_image = (
|
||||||
0.0 + new_img[:, :, 0:3]
|
0.0 + new_img[:, :, 0:3]
|
||||||
) # strip mask from init_img leaving only rgb channels
|
) # strip mask from init_img leaving only rgb channels
|
||||||
@ -153,7 +138,7 @@ def expand_image(
|
|||||||
hard_mask[:, origin_w // 2 :] = 255
|
hard_mask[:, origin_w // 2 :] = 255
|
||||||
|
|
||||||
hard_mask = cv2.copyMakeBorder(
|
hard_mask = cv2.copyMakeBorder(
|
||||||
hard_mask, top, bottom, left, right, cv2.BORDER_CONSTANT, value=255
|
hard_mask, top, bottom, left, right, cv2.BORDER_DEFAULT, value=255
|
||||||
)
|
)
|
||||||
mask_image = np.where(hard_mask > 0, mask_image, 0)
|
mask_image = np.where(hard_mask > 0, mask_image, 0)
|
||||||
return rgb_init_image.astype(np.uint8), mask_image.astype(np.uint8)
|
return rgb_init_image.astype(np.uint8), mask_image.astype(np.uint8)
|
||||||
|
Loading…
Reference in New Issue
Block a user