import gradio as gr import cv2 import numpy as np from skimage.metrics import structural_similarity as ssim def preprocess_image(image, blur_value): # Convert to grayscale gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Apply Gaussian blur to reduce noise blurred = cv2.GaussianBlur(gray, (blur_value, blur_value), 0) return blurred def compare_images(image1, image2, blur_value, technique, threshold_value): # Preprocess images gray1 = preprocess_image(image1, blur_value) gray2 = preprocess_image(image2, blur_value) # Compute SSIM between the two images score, diff = ssim(gray1, gray2, full=True) diff = (diff * 255).astype("uint8") if technique == "Adaptive Threshold": _, thresh = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY_INV) elif technique == "Otsu's Threshold": _, thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) else: # Simple Binary _, thresh = cv2.threshold(diff, threshold_value, 255, cv2.THRESH_BINARY) # Find contours of differences contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Filter out small noise using contour area threshold filtered_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 500] # Create a mask to isolate only the significant added object mask = np.zeros_like(image1, dtype=np.uint8) cv2.drawContours(mask, filtered_contours, -1, (255, 255, 255), thickness=cv2.FILLED) # Apply the mask to highlight the object added in the second image highlighted = cv2.bitwise_and(image2, mask) # Create a magenta overlay where changes occurred diff_colored = np.zeros_like(image1, dtype=np.uint8) diff_colored[:, :, 0] = thresh # Set blue channel to zero diff_colored[:, :, 1] = 0 # Set green channel to zero diff_colored[:, :, 2] = thresh # Set red channel to highlight in magenta # Combine the original image with the magenta overlay overlayed = cv2.addWeighted(image1, 0.7, diff_colored, 0.3, 0) return highlighted, overlayed def update_threshold_visibility(technique): return gr.update(visible=(technique == "Simple Binary")) with gr.Blocks() as demo: gr.Markdown("# Object Difference Highlighter\nUpload two images: one without an object and one with an object. The app will highlight only the newly added object and show the real differences in magenta overlayed on the original image.") with gr.Row(): img1 = gr.Image(type="numpy", label="Image Without Object") img2 = gr.Image(type="numpy", label="Image With Object") blur_slider = gr.Slider(minimum=1, maximum=15, step=2, value=5, label="Gaussian Blur") technique_dropdown = gr.Dropdown(["Adaptive Threshold", "Otsu's Threshold", "Simple Binary"], label="Thresholding Technique", value="Adaptive Threshold", interactive=True) threshold_slider = gr.Slider(minimum=0, maximum=255, step=1, value=50, label="Threshold Value", visible=False) technique_dropdown.change(update_threshold_visibility, inputs=[technique_dropdown], outputs=[threshold_slider]) output1 = gr.Image(type="numpy", label="Highlighted Differences") output2 = gr.Image(type="numpy", label="Raw Difference Overlay (Magenta)") btn = gr.Button("Process") btn.click(compare_images, inputs=[img1, img2, blur_slider, technique_dropdown, threshold_slider], outputs=[output1, output2]) demo.launch()