Logo-Inpaint / app.py
Jagrut Thakare
v1.2
a10b606
import cv2
import numpy as np
import gradio as gr
def find_bounding_box(mask):
"""Find the bounding box around the largest contour in the mask."""
mask = mask.astype(np.uint8)
_, binary_mask = cv2.threshold(mask, 1, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
x, y, w, h = cv2.boundingRect(np.vstack(contours))
return x, y, w, h
return None
def overlay_logo_on_image(original_img, mask, logo):
"""Overlay a scaled logo while maintaining aspect ratio and centering it in the bounding box."""
bbox = find_bounding_box(mask)
if bbox is None:
print("No bounding box found. Returning original image.")
return original_img
x, y, w, h = bbox
print(f"Bounding box found at: x={x}, y={y}, w={w}, h={h}")
# Get original logo dimensions
logo_h, logo_w = logo.shape[:2]
# Compute the scaling factor while maintaining aspect ratio
scale = min(w / logo_w, h / logo_h)
new_w, new_h = int(logo_w * scale), int(logo_h * scale)
# Resize the logo while maintaining aspect ratio
logo_resized = cv2.resize(logo, (new_w, new_h), interpolation=cv2.INTER_AREA)
# Ensure logo_resized has 4 channels (RGBA)
if logo_resized.shape[2] == 3:
logo_resized = cv2.cvtColor(logo_resized, cv2.COLOR_RGB2RGBA)
# Create a blank transparent canvas (RGBA)
logo_canvas = np.zeros((h, w, 4), dtype=np.uint8)
# Compute centering offsets
x_offset = (w - new_w) // 2
y_offset = (h - new_h) // 2
# Place the resized logo at the center of the bounding box
logo_canvas[y_offset:y_offset + new_h, x_offset:x_offset + new_w] = logo_resized
# Convert original image to 4-channel if necessary
if original_img.shape[2] == 3:
original_img = cv2.cvtColor(original_img, cv2.COLOR_RGB2RGBA)
# Blend the logo into the image using alpha blending
alpha = logo_canvas[:, :, 3] / 255.0
for c in range(3):
original_img[y:y+h, x:x+w, c] = (
(1 - alpha) * original_img[y:y+h, x:x+w, c] + alpha * logo_canvas[:, :, c]
)
return original_img
def process_images(original_img, mask, logo, progress=gr.Progress()):
"""Process images: overlay logo using uploaded mask."""
original_img = cv2.cvtColor(np.array(original_img), cv2.COLOR_RGB2BGR)
mask = np.array(mask)
print(f"Logo type before conversion: {type(logo)}, dtype: {getattr(logo, 'dtype', 'N/A')}")
logo = np.array(logo)
if logo.dtype != np.uint8:
logo = logo.astype(np.uint8)
logo = cv2.cvtColor(np.array(logo), cv2.COLOR_RGB2BGR)
if len(mask.shape) == 3:
mask = cv2.cvtColor(mask, cv2.COLOR_RGB2GRAY)
mask = (mask > 0).astype(np.uint8) * 255
print(f"Mask shape: {mask.shape}, unique values: {np.unique(mask)}")
result_img = overlay_logo_on_image(original_img, mask, logo)
result_img = cv2.cvtColor(result_img, cv2.COLOR_BGRA2RGBA) if result_img.shape[2] == 4 else cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
return result_img
with gr.Blocks() as demo :
gr.Markdown("## Inpaint Logo on Uploaded Mask")
with gr.Row() :
with gr.Column() :
with gr.Row():
original_img = gr.Image(label="Upload Original Image", type="numpy")
with gr.Row():
mask = gr.Image(label="Upload Mask (Binary)", type="numpy")
logo = gr.Image(label="Upload Logo", type="numpy")
btn = gr.Button("Submit")
with gr.Column() :
output = gr.Image(label="Output Image", format="png")
btn.click(fn=process_images, inputs=[original_img, mask, logo], outputs=output)
demo.launch(share=True, debug=True, show_error=True)