Spaces:
Sleeping
Sleeping
| import cv2 | |
| import numpy as np | |
| # === Inputs === | |
| background = cv2.imread('assets/BACKGROUND.png') # Background with circle | |
| input_image = cv2.imread('frame_00_00_31_738.png') # Full input image | |
| bbox = (495, 595, 801, 820) # Normalized (0–1000) format | |
| # Get input image size | |
| img_height, img_width = input_image.shape[:2] | |
| # Convert normalized bbox to absolute pixel coordinates | |
| y_min = int(bbox[0] / 1000.0 * img_height) | |
| x_min = int(bbox[1] / 1000.0 * img_width) | |
| y_max = int(bbox[2] / 1000.0 * img_height) | |
| x_max = int(bbox[3] / 1000.0 * img_width) | |
| # Bounding box size and center | |
| bbox_w = x_max - x_min | |
| bbox_h = y_max - y_min | |
| bbox_center_x = x_min + bbox_w // 2 | |
| bbox_center_y = y_min + bbox_h // 2 | |
| # Target circle (on background) | |
| circle_center = (296, 126) | |
| circle_radius = 77 | |
| circle_diameter = 2 * circle_radius | |
| # === 1. Compute scale so the bbox fits inside the circle === | |
| scale = min(circle_diameter / bbox_w, circle_diameter / bbox_h) | |
| # === 2. Resize the entire input image === | |
| new_width = int(img_width * scale) | |
| new_height = int(img_height * scale) | |
| resized_image = cv2.resize(input_image, (new_width, new_height)) | |
| # === 3. Compute new center of the bbox after scaling === | |
| new_bbox_center_x = int(bbox_center_x * scale) | |
| new_bbox_center_y = int(bbox_center_y * scale) | |
| # === 4. Compute offset so that bbox center aligns with circle center === | |
| offset_x = circle_center[0] - new_bbox_center_x | |
| offset_y = circle_center[1] - new_bbox_center_y | |
| # === 5. Paste resized image onto background === | |
| # Create a blank canvas same size as background | |
| canvas = np.zeros_like(background) | |
| # Compute region where image will be placed | |
| start_x = max(offset_x, 0) | |
| start_y = max(offset_y, 0) | |
| end_x = min(start_x + new_width, background.shape[1]) | |
| end_y = min(start_y + new_height, background.shape[0]) | |
| src_start_x = max(-offset_x, 0) | |
| src_start_y = max(-offset_y, 0) | |
| # Copy region from resized image to canvas | |
| canvas[start_y:end_y, start_x:end_x] = resized_image[src_start_y:src_start_y + (end_y - start_y), src_start_x:src_start_x + (end_x - start_x)] | |
| mask = cv2.imread('circle_mask.png', cv2.IMREAD_GRAYSCALE) | |
| mask = cv2.resize(mask, (background.shape[1], background.shape[0])) # Ensure same size | |
| # Blend entire image (for use outside circle) | |
| alpha = 0.3 | |
| beta = 1.0 - alpha | |
| blended = cv2.addWeighted(canvas, alpha, background, beta, 0) | |
| # Create 3-channel version of mask | |
| mask_3c = cv2.merge([mask, mask, mask]) | |
| # Create inverse mask (inside circle) | |
| inv_mask = cv2.bitwise_not(mask_3c) | |
| # Apply blended background where mask is white (outside the circle) | |
| outside = cv2.bitwise_and(blended, mask_3c) | |
| # Apply original canvas (input image) where mask is black (inside the circle) | |
| inside = cv2.bitwise_and(canvas, inv_mask) | |
| # Combine both | |
| combined = cv2.add(outside, inside) | |
| # === 6. Save result === | |
| cv2.imwrite('output.png', combined) |