Spaces:
Sleeping
Sleeping
import os | |
import sys | |
import cv2 | |
import numpy as np | |
from PIL import Image | |
debug = False | |
def gray3d_to_2d(grayscale: np.ndarray) -> np.ndarray: | |
channel = grayscale.shape[2] if grayscale.ndim == 3 else 1 | |
if channel!=1: | |
text = f"grayscale shape = {grayscale.shape} channel = {channel} ndim = {grayscale.ndim} size = {grayscale.size}" | |
raise ValueError(f"color maybe rgb or rgba {text}") | |
if grayscale.ndim == 2: | |
return grayscale | |
return np.squeeze(grayscale) | |
def pil_to_cv(image): | |
cv_image = np.array(image, dtype=np.uint8) | |
if cv_image.shape[2] == 3: # γ«γ©γΌ | |
cv_image = cv2.cvtColor(cv_image, cv2.COLOR_RGB2BGR) | |
elif cv_image.shape[2] == 4: # | |
cv_image = cv2.cvtColor(cv_image, cv2.COLOR_RGBA2BGR) | |
return cv_image | |
def blend_rgb_images(image1: np.ndarray, image2: np.ndarray, mask: np.ndarray) -> np.ndarray: | |
if image1.shape != image2.shape or image1.shape[:2] != mask.shape: | |
raise ValueError("not same shape") | |
# η»εγ float εγ«ε€ζ | |
image1 = image1.astype(float) | |
image2 = image2.astype(float) | |
# mask to 3 chan 0 -1 value | |
alpha = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR).astype(float) / 255.0 | |
# calcurate blend | |
blended = (1 - alpha) * image1 + alpha * image2 | |
return blended.astype(np.uint8) | |
def process_cvinpaint(image,mask_image,inpaint_radius,blur_radius,edge_expand,inpaint_mode,dilate=0): | |
#print("process cvinpaint") | |
#print(blur_radius,",",edge_expand) | |
cv_image = pil_to_cv(image) | |
cv_mask = pil_to_cv(mask_image) | |
cv_gray = cv2.cvtColor(cv_mask,cv2.COLOR_BGR2GRAY) | |
mask = gray3d_to_2d(cv_gray) | |
if dilate>0: | |
kernel = np.ones((dilate, dilate), np.uint8) | |
mask = cv2.dilate(mask, kernel, iterations=1) | |
#cv2.imwrite("_mask.jpg",mask) | |
#cv2.imwrite("_image.jpg",cv_image) | |
mode = cv2.INPAINT_TELEA if inpaint_mode == "Telea" else cv2.INPAINT_NS | |
img_inpainted = cv2.inpaint(cv_image, mask,inpaint_radius, mode) | |
if debug: | |
cv2.imwrite("close_eye_inpaint.jpg",img_inpainted) | |
## blur | |
if blur_radius > 0: | |
if blur_radius%2==0: | |
blur_radius += 1 | |
#print(blur_radius) | |
blurred_image = cv2.GaussianBlur(img_inpainted, (blur_radius, blur_radius), 0) #should be odd | |
if debug: | |
cv2.imwrite("close_eye_inpaint_burred.jpg",blurred_image) | |
else: | |
blurred_image = img_inpainted | |
# expand edge and blur | |
kernel = np.ones((edge_expand, edge_expand), np.uint8) | |
extend_mask = cv2.dilate(mask, kernel, iterations=1) | |
if edge_expand > 0 and blur_radius > 0: | |
extend_burred_mask = cv2.GaussianBlur(extend_mask, (blur_radius, blur_radius), 0) | |
else: | |
extend_burred_mask = extend_mask | |
img_inpainted = blend_rgb_images(img_inpainted,blurred_image,extend_burred_mask) | |
output_image = img_inpainted.copy() | |
if output_image.shape[2] == 3: # γ«γ©γΌ | |
output_image = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB) | |
return Image.fromarray(output_image),Image.fromarray(mask) | |
if __name__ == "__main__": | |
image = Image.open(sys.argv[1]) | |
mask = Image.open(sys.argv[2]) | |
output = process_cvinpaint(image,mask) | |
output.save(sys.argv[3]) |