Stream asset reset v7, cleaning background and transparency fixes. 2026-01-29 16:37

This commit is contained in:
2026-01-29 16:38:17 +01:00
parent afa0e3c662
commit 177049e470
14 changed files with 180 additions and 165 deletions

View File

@@ -19,7 +19,8 @@ function createWindow() {
title: 'Mrtva Dolina - Death Valley'
});
mainWindow.loadFile('index.html');
// Fix path to index.html (it's one level up from scripts/)
mainWindow.loadFile(path.join(__dirname, '../index.html'));
mainWindow.webContents.openDevTools();
mainWindow.on('closed', () => {

View File

@@ -1,108 +1,107 @@
import cv2
import numpy as np
import os
def slice_stream_assets():
src_path = '/Users/davidkotnik/.gemini/antigravity/brain/07019d04-a214-43ab-9565-86f4e8f17e5b/uploaded_media_1769607894587.jpg'
print(f"Loading {src_path}")
img = cv2.imread(src_path)
if img is None: return
# 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}")
# 1. CLEAN BACKGROUND (GrabCut)
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
h, w = img.shape[:2]
cv2.grabCut(img, mask, (10, 10, w-20, h-20), bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask_final = np.where((mask==2)|(mask==0),0,1).astype('uint8')
# Apply Alpha
b, g, r = cv2.split(img)
alpha = mask_final * 255
img_rgba = cv2.merge([b, g, r, alpha])
# 2. CREATE 'HEAD' (Pipe Only)
# The pipe is roughly the top 40%? Let's crop visually based on the image structure.
# The pipe is top-right.
# Let's say we keep the top half as the "Start".
# And we take a middle slice as the "Segment".
# Finding the pipe:
# Based on the image, the pipe drain is at the top.
# Let's crop `head` from y=0 to y=0.45*h
cut_y = int(h * 0.45)
head_img = img_rgba[0:cut_y, :]
# Crop transparent borders from head
coords = cv2.findNonZero(head_img[:,:,3]) # Alpha
if coords is not None:
x, y, cw, ch = cv2.boundingRect(coords)
head_img = head_img[y:y+ch, x:x+cw]
# 3. CREATE 'SEGMENT' (Water Channel)
# We take a slice from the middle-bottom.
# Crop from y=0.45*h to y=0.85*h (skip very bottom tip?)
# Actually, let's take a nice chunk that can be tiled.
# The channel is diagonal. Tiling diagonal is hard without overlap.
# Let's just crop the rest of the stream as one big piece for now.
body_img = img_rgba[cut_y:, :]
# Crop transparent borders from body
coords = cv2.findNonZero(body_img[:,:,3])
if coords is not None:
x, y, cw, ch = cv2.boundingRect(coords)
body_img = body_img[y:y+ch, x:x+cw]
# 4. SOFTEN EDGES (To fix floating walls)
# Applied to both Head and Body.
# We want to fade out the BOTTOM edge of the mask, so the "wall" blends into the grass.
def soften_bottom_edge(image):
h, w = image.shape[:2]
# Create a gradient mask for the bottom 20 pixels
grad_h = 30
if h < grad_h: return image # Too small
# We modify the alpha channel
alpha = image[:,:,3]
# We need to detect where the "bottom" of the object is.
# Since it's diagonal, it's tricky.
# Simple hack: Erode the alpha slightly to sharpen the cut, then blur it?
# Or just blur the edges?
# Let's try blurring the alpha channel to soften the hard cut against the grass.
# Only on the edges.
# Get edge mask
edges = cv2.Canny(alpha, 100, 200)
# Dilate edges to get a rim
rim = cv2.dilate(edges, np.ones((5,5),np.uint8))
# Blur alpha
blurred_alpha = cv2.GaussianBlur(alpha, (7,7), 0)
# Apply blurred alpha where rim is
# image[:,:,3] = np.where(rim>0, blurred_alpha, alpha)
# Actually, let's just do a global soft outline.
image[:,:,3] = blurred_alpha
return image
# head_img = soften_bottom_edge(head_img)
# body_img = soften_bottom_edge(body_img)
# (Skipping blur for now, plain cut is cleaner if geometry is right)
# Save
base_dir = '/Users/davidkotnik/repos/novafarma/assets/DEMO_FAZA1/Environment'
if not os.path.exists(base_dir): os.makedirs(base_dir, exist_ok=True)
cv2.imwrite(os.path.join(base_dir, 'stream_head.png'), head_img)
cv2.imwrite(os.path.join(base_dir, 'stream_body.png'), body_img)
print("Sliced stream into head and body.")
if __name__ == "__main__":
slice_stream_assets()