108 lines
2.8 KiB
Python
108 lines
2.8 KiB
Python
|
|
|
|
|
|
|
|
|
|
import cv2
|
|
import numpy as np
|
|
import os
|
|
|
|
# Paths
|
|
input_path = '/Users/davidkotnik/.gemini/antigravity/brain/8233d64e-0c17-43b1-b8b5-fbc41754e56b/uploaded_media_1769679216460.jpg'
|
|
output_dir = '/Users/davidkotnik/repos/novafarma/assets/DEMO_FAZA1/Environment/'
|
|
|
|
# Ensure output dir exists
|
|
if not os.path.exists(output_dir):
|
|
os.makedirs(output_dir)
|
|
|
|
# Read image
|
|
img = cv2.imread(input_path, cv2.IMREAD_COLOR)
|
|
if img is None:
|
|
print("Error loading input image")
|
|
exit(1)
|
|
|
|
h, w = img.shape[:2]
|
|
print(f"Image loaded: {w}x{h}")
|
|
|
|
# Convert to BGRA
|
|
img_rgba = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
|
|
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
|
|
|
|
# --- 1. REMOVE BACKGROUND (Checkerboard/White) ---
|
|
# Strategy: The background is bright (White/Light Gray). The content (Mud, Pipe, Debris) is darker.
|
|
# Threshold on Value (V) channel.
|
|
# Let's verify histogram or min/max.
|
|
# Or just a hard threshold.
|
|
# Mud is dark. Pipe is dark gray.
|
|
# Debris is dark.
|
|
# Checkerboard is > 200 usually.
|
|
|
|
thresh_val = 190
|
|
# Create mask where Value > 190 -> Background
|
|
_, mask_bg_bright = cv2.threshold(hsv[:, :, 2], thresh_val, 255, cv2.THRESH_BINARY)
|
|
|
|
# Also check for Low Saturation for the checkerboard?
|
|
# Checkerboard is grayscale (S near 0).
|
|
# Pipe is also grayscale.
|
|
# But Pipe is Darker.
|
|
# So Brightness threshold should handle it.
|
|
|
|
# Refine mask:
|
|
# Remove small holes in background mask?
|
|
# Use morphological open
|
|
kernel = np.ones((3,3), np.uint8)
|
|
mask_bg_bright = cv2.morphologyEx(mask_bg_bright, cv2.MORPH_OPEN, kernel)
|
|
|
|
# --- 2. REMOVE GREEN TRIANGLE ---
|
|
# Green range
|
|
lower_green = np.array([35, 40, 40])
|
|
upper_green = np.array([90, 255, 255])
|
|
mask_green = cv2.inRange(hsv, lower_green, upper_green)
|
|
|
|
# Combine Background and Green masks
|
|
# We want to remove (set alpha 0) where mask is BG or Green.
|
|
mask_remove = cv2.bitwise_or(mask_bg_bright, mask_green)
|
|
|
|
# Set alpha
|
|
# Start with opaque (255)
|
|
img_rgba[:, :, 3] = 255
|
|
# Set 0 where removal mask is active
|
|
img_rgba[mask_remove > 0, 3] = 0
|
|
|
|
# Smooth edges slightly
|
|
# cv2.GaussianBlur on alpha channel?
|
|
# Or erode the alpha slightly to remove fringes.
|
|
# Let's erode the opaque region.
|
|
alpha = img_rgba[:, :, 3]
|
|
alpha = cv2.erode(alpha, kernel, iterations=1)
|
|
img_rgba[:, :, 3] = alpha
|
|
|
|
|
|
# --- 3. CROP AND SAVE ---
|
|
# Crop to content
|
|
coords = cv2.findNonZero(img_rgba[:, :, 3])
|
|
if coords is not None:
|
|
x, y, w_content, h_content = cv2.boundingRect(coords)
|
|
|
|
# Padding
|
|
padding = 2
|
|
x = max(0, x - padding)
|
|
y = max(0, y - padding)
|
|
w_content = min(w - x, w_content + 2*padding)
|
|
h_content = min(h - y, h_content + 2*padding)
|
|
|
|
cropped_main = img_rgba[y:y+h_content, x:x+w_content]
|
|
else:
|
|
cropped_main = img_rgba # Fallback
|
|
|
|
# Save FINAL asset v7
|
|
output_path = os.path.join(output_dir, 'stream_final_v7.png')
|
|
cv2.imwrite(output_path, cropped_main)
|
|
print(f"Saved V7 asset to {output_path}")
|
|
|
|
|
|
|
|
|
|
|
|
|