File size: 2,833 Bytes
0914e96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File: ai-service/core/utils.py

import os
import cv2
import numpy as np
from sklearn.cluster import KMeans
import urllib.request
import ssl
from supabase import create_client, Client
from dotenv import load_dotenv

# Load environment variables from the root .env file
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
load_dotenv(dotenv_path=os.path.join(ROOT_DIR, '.env'))

def get_supabase_client() -> Client:
    """
    Creates and returns a Supabase client.
    Raises ValueError if credentials are not set in the environment.
    """
    try:
        url = os.environ.get("SUPABASE_URL")
        key = os.environ.get("SUPABASE_SERVICE_KEY") # We use service key for backend tasks
        if not url or not key:
            raise ValueError("Supabase credentials (URL or Service Key) are not set.")
        return create_client(url, key)
    except Exception as e:
        print(f"🔴 FATAL: Could not create Supabase client: {e}")
        raise # Re-raise the exception to stop the app if this fails.

def extract_colors_from_url(image_url: str, num_colors=4) -> list:
    """
    Downloads an image from a URL and returns the top N dominant colors in Hex format.
    Requires: opencv-python-headless, scikit-learn, numpy
    """
    try:
        print(f"🎨 Extracting colors from: {image_url}")
        
        # 1. Handle SSL Context (Dev environments often fail strict SSL)
        context = ssl._create_unverified_context()
        
        # 2. Download Image directly to memory
        with urllib.request.urlopen(image_url, context=context) as req:
            arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
            img = cv2.imdecode(arr, -1)

        if img is None:
            return []

        # 3. Setup Image (Convert BGR to RGB, Resize for speed)
        # If image has alpha channel (Transparency), remove it
        if img.shape[2] == 4:
            img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
            
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img, (100, 100), interpolation=cv2.INTER_AREA)
        
        # Reshape to list of pixels
        img = img.reshape((img.shape[0] * img.shape[1], 3))

        # 4. Use KMeans clustering to find dominant colors
        kmeans = KMeans(n_clusters=num_colors, n_init='auto')
        kmeans.fit(img)
        colors = kmeans.cluster_centers_
        
        # 5. Convert to Hex
        hex_colors = []
        for color in colors:
            hex_code = '#{:02x}{:02x}{:02x}'.format(int(color[0]), int(color[1]), int(color[2]))
            hex_colors.append(hex_code)
            
        return hex_colors

    except Exception as e:
        print(f"⚠️ Error extracting colors: {str(e)}")
        # Return fallback gray/black if extraction fails
        return ["#000000", "#808080"]