Download Game! Currently 99 players. Last logged in:FarlissQumniSlimyVihaan

Blitzer's Blog >> 72608

Back to blogs index
Posted: 20 Sep 2026 17:50 [ permalink ]
import cv2
import numpy as np
import torch
import pytesseract
from PIL import Image, ImageGrab
from transformers import CLIPProcessor, CLIPModel
import time

# --- ASETUKSET ---
VIEWPORT_TOP = 120 # Ohitetaan selaimen ylC$palkki (CDP/Tabs)
ICON_LABELS = [
    "a paperclip icon", "a microphone icon", "a smiley face icon", 
    "a send message button", "a user profile picture", 
    "a magnifying glass search icon", "random background noise"
]

def load_clip():
    print("[*] 1. Ladataan semanttinen Vision-malli (CLIP)...")
    model_id = "openai/clip-vit-base-patch32"
    return CLIPModel.from_pretrained(model_id), CLIPProcessor.from_pretrained(m
odel_id)

def detect_frames(gray_img):
    print("[*] 2. Analysoidaan kC$yttC6liittymC$n pC$C$rakenteet (Layout)...")
    screen_h, screen_w = gray_img.shape
    viewport_gray = gray_img[VIEWPORT_TOP:, :]
    
    edges = cv2.Canny(viewport_gray, 50, 150)
    col_sums = np.sum(edges, axis=0)
    
    search_start = int(screen_w * 0.20)
    search_end = int(screen_w * 0.50)
    middle_cols = col_sums[search_start:search_end]
    
    divider_x = search_start + np.argmax(middle_cols)
    if col_sums[divider_x] < (screen_h * 0.1 * 255): 
        divider_x = int(screen_w * 0.30)
        
    return [
        {"id": "Frame_1_Sidebar", "x": 0, "y": VIEWPORT_TOP, "w": divider_x,
"h": screen_h - VIEWPORT_TOP},
        {"id": "Frame_2_Main", "x": divider_x, "y": VIEWPORT_TOP, "w":
screen_w - divider_x, "h": screen_h - VIEWPORT_TOP}
    ]

def extract_nodes(gray_img, frame):
    fx, fy, fw, fh = frame["x"], frame["y"], frame["w"], frame["h"]
    roi_gray = gray_img[fy:fy+fh, fx:fx+fw]
    
    edges = cv2.Canny(roi_gray, 50, 150)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 5))
    dilated = cv2.dilate(edges, kernel, iterations=1)
    contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
    
    nodes = []
    for i, c in enumerate(contours):
        x, y, w, h = cv2.boundingRect(c)
        if w < 12 or h < 12 or w > fw * 0.9: continue
            
        crop = roi_gray[y:y+h, x:x+w]
        text = pytesseract.image_to_string(crop, config='--psm 7').strip()
        text = "".join([ch for ch in text if ch.isalnum() or ch in "
.,?!-()/:"])
        
        abs_x, abs_y = fx + x, fy + y
        
        # Jos teksti on riittC$vC$n pitkC$, se on tekstiC$. Muuten ikoni.
        if len(text) > 2:
            nodes.append({"id": f"{frame['id']}_n{i}", "type": "TextNode",
"content": text, "box": (abs_x, abs_y, w, h)})
        else:
            nodes.append({"id": f"{frame['id']}_n{i}", "type": "IconNode",
"content": "Unknown", "box": (abs_x, abs_y, w, h)})
            
    # JC$rjestetC$C$n ylhC$C$ltC$ alas
    nodes.sort(key=lambda n: (n['box'][1] // 20, n['box'][0]))
    return nodes

def enrich_icons_with_clip(pil_img, nodes, clip_model, clip_processor):
    print(f"[*] 3. Rikastetaan ikonit tekoC$lyllC$ (Semanttinen analyysi)...")
    icon_nodes = [n for n in nodes if n['type'] == 'IconNode']
    if not icon_nodes: return nodes
    
    crops = []
    for node in icon_nodes:
        x, y, w, h = node['box']
        pad = 4 # Pieni marginaali auttaa CLIPiC$ nC$kemC$C$n ikonin rajat
        box = (max(0, x-pad), max(0, y-pad), min(pil_img.width, x+w+pad),
min(pil_img.height, y+h+pad))
        crops.append(pil_img.crop(box).convert("RGB"))
        
    # Batch-ajo: Kaikki ikonit kerralla CLIPin lC$pi
    inputs = clip_processor(text=ICON_LABELS, images=crops, return_tensors="pt"
, padding=True)
    with torch.no_grad():
        outputs = clip_model(**inputs)
        
    logits = outputs.logits_per_image.softmax(dim=1).numpy()
    
    # YhdistetC$C$n tulokset takaisin solmuihin
    for i, probs in enumerate(logits):
        best_idx = np.argmax(probs)
        best_score = probs[best_idx] * 100
        best_label = ICON_LABELS[best_idx]
        
        if best_score > 50.0 and "noise" not in best_label:
            icon_nodes[i]['content'] = f"{best_label} ({best_score:.0f}%)"
        else:
            icon_nodes[i]['content'] = "Generic Icon"
            
    return nodes

def generate_markdown(frames, all_nodes):
    print("[*] 4. Rakennetaan AST-MD semanttinen kartta...")
    md = "# AST-MD: Rikastettu KC$yttC6liittymC$kartta

"
    
    for frame in frames:
        md += f"## {frame['id']}
"
        md += f"> Rajat: X:{frame['x']}, Y:{frame['y']}, W:{frame['w']},
H:{frame['h']}

"
        
        frame_nodes = [n for n in all_nodes if n['id'].startswith(frame['id'])]
        for n in frame_nodes:
            x, y, w, h = n['box']
            if n['type'] == 'TextNode':
                md += f"  - `[{n['id']}]` **Text**: \"{n['content']}\" (X:{x},
Y:{y})
"
            else:
                md += f"  - `[{n['id']}]` **Icon**: *{n['content']}* (X:{x},
Y:{y})
"
        md += "
"
    return md

def main():
    start_time = time.time()
    clip_model, clip_processor = load_clip()
    
    pil_img = ImageGrab.grab()
    cv_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
    gray_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)