import gradio as gr import numpy as np import cv2 import utils from predict import build_predictor ID_PHOTO_IMAGE_DEMO = "./images/idphoto.jpg" MC_PHOTO_BG = "Red" MC_PHOTO_SIZE = (413, 626) MC_PHOTO_WIFE_IMAGE_DEMO = "./images/wife.jpg" MC_PHOTO_HUSBAND_IMAGE_DEMO = "./images/husband.jpg" predictor = build_predictor() sizes_play = utils.size_play() def crop(img, alpha, thr=0.001): """ Crop the image and alpha according to alpha mask. Args: img(numpy:ndarray): The image array. alpha(numpy:ndarray): The alpha corresponding to the image. thr(float): The threshold used to generate the alpha mask. Returns: img_cropped(numpy:ndarray): Image after crop. alpha_cropped(numpy:ndarray): alpha after crop. """ _, mask = cv2.threshold(alpha, 0, 255, cv2.THRESH_BINARY, thr) cnt, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) x, y, w, h = cv2.boundingRect(cnt[0]) return img[y: y + h, x: x + w], alpha[y: y + h, x: x + w] def copy_img_to_bg(img, alpha, target_h, target_x, bg_color, bg_size): """ Copy img and alpha to the corresponding background respectively. Args: img(numpy:ndarray): The image array. alpha(numpy:ndarray): The alpha corresponding to the image. target_h(int): The target height of img in background. target_x(int): The target position of the img's x-center in the background. bg_color(str): The color of background, the options are "White"、"Blue"、"Red". bg_size(tuple): The size of background. Returns: res_img(numpy:ndarray): Result after copy img to background. res_alpha(numpy:ndarray): Result after copy alpha to background. """ bg_h, bg_w = bg_size img_h, img_w, _ = img.shape r = 1.0 * img_h / target_h target_w = int(img_w / r) res_img = np.ones((bg_h, bg_w, 3)) * utils.COLOR_MAP[bg_color] res_alpha = np.zeros((bg_h, bg_w)) img = cv2.resize(img, (target_w, target_h), interpolation=cv2.INTER_AREA) alpha = cv2.resize(alpha, (target_w, target_h), interpolation=cv2.INTER_AREA) x1 = int(max(0, target_x - target_w / 2)) y1 = int(max(0, bg_h - target_h)) x2 = int(min(bg_w, x1+target_w)) y2 = int(min(bg_h, y1+target_h)) act_w = x2 - x1 act_h = y2 - y1 res_img[y1: y2, x1: x2] = img[:act_h, :act_w] res_alpha[y1: y2, x1: x2] = alpha[:act_h, :act_w] return res_img, res_alpha def get_mc_photo_app_output(wife, husband): """ Composite marriage certificate photo Args: wife(numpy:ndarray): The wife image array. husband(numpy:ndarray): The husband image array. Returns: res(numpy:ndarray): The composited marriage certificate photo. res_download(str): The path of res. """ alpha_wife = predictor.run(wife) alpha_husband = predictor.run(husband) _, wife_fg = utils.bg_replace(wife, alpha_wife, bg_name=MC_PHOTO_BG) husband, _ = utils.bg_replace(husband, alpha_husband, bg_name=MC_PHOTO_BG) wife_fg, alpha_wife = crop(wife_fg, alpha_wife) husband, alpha_husband = crop(husband, alpha_husband) wife_fg, alpha_wife = copy_img_to_bg(wife_fg, alpha_wife, 338, 225, MC_PHOTO_BG, MC_PHOTO_SIZE) husband, alpha_husband = copy_img_to_bg(husband, alpha_husband, 375, 401, MC_PHOTO_BG, MC_PHOTO_SIZE) alpha_wife = alpha_wife[:, :, None] / 255.0 res = (wife_fg * alpha_wife + (1 - alpha_wife) * husband).astype(np.uint8) res_download = utils.download(res, "Large") return res, res_download def get_id_photo_output(img, size, bg, download_size): """ Get the special size and background photo. Args: img(numpy:ndarray): The image array. size(str): The size user specified. bg(str): The background color user specified. download_size(str): The size for image saving. """ alpha = predictor.run(img) res, _ = utils.bg_replace(img, alpha, bg_name=bg) size_index = sizes_play.index(size) res = utils.adjust_size(res, size_index) res_download = utils.download(res, download_size) return res, res_download def clear_id_photo_all(): utils.delete_result() return None, None, sizes_play[0], 'White', 'Large', None def clear_mc_photo_all(): utils.delete_result() return None, None, None, None with gr.Blocks() as demo: gr.Markdown("""# ID and MC(Marriage Certificate) Photo DIY""") gr.Markdown( """Tips: Please upload photos with good posture, center portrait, crown free, no jewelry, ears and eyebrows exposed.""" ) with gr.Tab("IDPhoto"): id_photo_img_in = gr.Image(value=ID_PHOTO_IMAGE_DEMO, label="Input image") with gr.Row(): id_photo_size = gr.Dropdown(sizes_play, label="Sizes", value=sizes_play[0]) id_photo_bg = gr.Radio( ["White", "Red", "Blue"], label="Background color", value='White') id_photo_download_size = gr.Radio( ["Small", "Middle", "Large"], label="File size (affects image quality)", value='Large', interactive=True) with gr.Row(): id_photo_clear_btn = gr.Button("Clear") id_photo_submit_btn = gr.Button("Submit") id_photo_img_out = gr.Image(label="Output image", interactive=False).style(height=300) id_photo_downloaded_img = gr.File(label='Image download').style(height=50) id_photo_clear_btn.click( fn=clear_id_photo_all, inputs=None, outputs=[id_photo_img_in, id_photo_img_out, id_photo_size, id_photo_bg, id_photo_download_size, id_photo_downloaded_img]) id_photo_submit_btn.click( fn=get_id_photo_output, inputs=[id_photo_img_in, id_photo_size, id_photo_bg, id_photo_download_size], outputs=[id_photo_img_out, id_photo_downloaded_img]) with gr.Tab("MCPhoto"): with gr.Row(): mc_photo_img_wife = gr.Image(value=MC_PHOTO_WIFE_IMAGE_DEMO, label="Wife", interactive=True) mc_photo_img_husband = gr.Image(value=MC_PHOTO_HUSBAND_IMAGE_DEMO, label="Husband", interactive=True) with gr.Row(): mc_photo_clear_button = gr.Button("Clear") mc_photo_submit_button = gr.Button("Submit") mc_photo_img_out = gr.Image(label="Output image", interactive=False).style(height=300) mc_photo_download_img = gr.File(label='Image download').style(height=50) mc_photo_clear_button.click( fn=clear_mc_photo_all, inputs=None, outputs=[mc_photo_img_wife, mc_photo_img_husband, mc_photo_img_out, mc_photo_download_img]) mc_photo_submit_button.click( fn=get_mc_photo_app_output, inputs=[mc_photo_img_wife, mc_photo_img_husband], outputs=[mc_photo_img_out, mc_photo_download_img]) gr.Markdown( """This application is supported by [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg). If you have any question or feature request, welcome to raise issues on [GitHub](https://github.com/PaddlePaddle/PaddleSeg/issues). BTW, a star is a great encouragement for us, thanks! ^_^""" ) gr.Button.style(1) demo.launch(share=True)