Zawartość: - Koncepcja 0.1 oraz rozszerzona Koncepcja 0.2 (model domenowy, architektura, mapowanie cel→metryki→usługi AI, wymienialność modeli, model danych) - Katalog 15 celów analiz kognitywnych - Specyfikacja procesu AI + opis procesów źródłowych - Pytania do koncepcji - Materiały źródłowe: info.md, n8n.json Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
16 KiB
Specyfikacja procesu: analiza uwagi wzrokowej kreacji reklamowych
Opis logiki procesu niezależny od narzędzia orkiestrującego, przeznaczony do implementacji jako komponent oprogramowania (np. usługa backendowa / pipeline). Definiuje: dane wejściowe, kontrakty zewnętrznych usług AI, kolejność i równoległość wywołań, model danych wynikowych oraz logikę prezentacji.
1. Cel i zakres
System przyjmuje pojedynczy obraz (kreację reklamową / grafikę) i zwraca zestaw analiz:
- Rozumienie zawartości — jakie obiekty są na obrazie i gdzie się znajdują.
- Predykcja uwagi wzrokowej (saliency) — gdzie skupi się wzrok odbiorcy; trzy niezależne modele dla walidacji krzyżowej.
Wynikiem są dane (lista obiektów z ramkami, mapy uwagi) oraz pochodne wizualizacje. Proces jest bezstanowy — jedno wejście (obraz) → jeden komplet wyników.
2. Architektura logiczna
┌────────────────────┐
│ Wejście: obraz │
└─────────┬──────────┘
▼
┌────────────────────┐
│ Preprocessing │ bytes + base64 + mime + (w,h)
└─────────┬──────────┘
│
┌──────────────┼───────────────┬───────────────┬───────────────┐
▼ (łańcuch A) ▼ (B) ▼ (C) ▼ (D)
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ LLaVA │ │ DeepGaze │ │ UNISAL │ │ ASM │
│ (etykiety)│ │(saliency)│ │(saliency)│ │(2× saliency)
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
▼ │ │ │
┌──────────────┐ │ │ │
│ Grounding │ │ │ │
│ DINO (boxy) │ │ │ │
└────┬─────────┘ │ │ │
│ ▼ ▼ ▼
▼ ┌──────────────────────────────────────┐
┌──────────────┐ │ Agregacja wyników saliency │
│ Wynik: │ └──────────────────┬───────────────────┘
│ detekcja │ ▼
└──────────────┘ ┌──────────────────────────┐
│ Artefakty wyjściowe: │
│ • overlay boxów │
│ • nakładka heatmapy │
│ • porównanie 2×2 │
└──────────────────────────┘
Kluczowe zależności:
- Łańcuch A jest sekwencyjny: Grounding DINO potrzebuje etykiet z LLaVA.
- Zadania B, C, D oraz cały łańcuch A są względem siebie niezależne → wykonywane równolegle.
- Punkt agregacji czeka na zakończenie wymaganych zadań przed złożeniem danego artefaktu.
3. Dane wejściowe i preprocessing
Wejście: plik graficzny (PNG lub JPEG).
Preprocessing — z jednego uploadu przygotuj reprezentację współdzieloną przez wszystkie usługi:
ImageInput {
bytes : binary // oryginalne bajty pliku (do multipart/form-data)
base64 : string // base64 bez prefiksu data: (do osadzania i obliczeń)
mime : "image/png" | "image/jpeg"
width : int
height : int
}
mime,width,heightustal standardową biblioteką do obrazów (np. Pillow /image-size/sharp).Uwaga: pierwotna implementacja parsowała nagłówki ręcznie (PNG:
width@offset16,height@offset20jako uint32 BE; JPEG: skan markerówSOF0 0xC0/SOF2 0xC2). W docelowym kodzie użyj gotowej biblioteki — wymiary i tak są potrzebne tylko do pozycjonowania ramek i renderowania (sekcja 7).base64służy do: (a) osadzania oryginału w wizualizacjach, (b) blendu pikselowego.bytessłuży do wszystkich wywołań usług (pole multipartimagelubfile).
4. Wewnętrzny model danych (wyników)
DetectionResult {
objects : [ { object_type: string,
bbox_xyxy: [x1, y1, x2, y2], // piksele, układ XYXY
score: float } ] // 0..1
model_id? : string
threshold? : float
}
SaliencyMap {
source : "deepgaze" | "unisal" | "asm_detailed" | "asm_general"
image_base64 : string
mime : string
}
AnalysisResult {
image : ImageInput
detection : DetectionResult
saliency : SaliencyMap[] // 4 pozycje: deepgaze, unisal, asm_detailed, asm_general
}
5. Zewnętrzne usługi AI — kontrakty API
Wszystkie usługi to HTTP POST z ciałem multipart/form-data zawierającym obraz.
Adresy hostów i token pochodzą z konfiguracji / magazynu sekretów (sekcja 8).
Każde wywołanie powinno mieć skończony timeout i być odporne na błędy (sekcja 9).
Kształty odpowiedzi oznaczone „(wnioskowane)" odtworzono na podstawie sposobu konsumpcji danych — przy implementacji potwierdź je z dokumentacją/realnymi odpowiedziami usług.
5.1. LLaVA — ekstrakcja typów obiektów
Multimodalny model wizualno-językowy; zwraca listę kategorii obiektów widocznych na obrazie.
POST http://{LLAVA_HOST}/llava-api/v1/get-object-types
Headers:
accept: application/json
Authorization: Bearer {TOKEN}
Body (multipart/form-data):
temperature = 0.2 // niska → powtarzalność
top_p = 0.9
image = <plik>
Odpowiedź (wnioskowane):
{ "labels": ["person", "bottle", "logo", ...] }
Transformacja po stronie klienta: połącz labels w jeden ciąg rozdzielony przecinkami
("person, bottle, logo") — wejście dla Grounding DINO.
5.2. Grounding DINO — detekcja obiektów (bounding boxy)
Otwarto-zbiorowa (zero-shot) detekcja sterowana tekstem: dla podanych etykiet zwraca ramki.
POST http://{GROUNDING_DINO_HOST}/grounding-dino-api/v1/get-objects-bboxes
Headers:
accept: application/json
Authorization: Bearer {TOKEN}
Body (multipart/form-data):
object_types = "{labels_z_LLaVA}" // np. "person, bottle, logo"
max_objects = 50
base64 = false
image = <plik>
Odpowiedź (wnioskowane):
{
"objects_bboxes": [
{ "object_type": "logo",
"bbox_coords_xyxy": [x1, y1, x2, y2],
"score": 0.87 }
],
"model_id": "...", // opcjonalnie
"threshold": 0.3, // opcjonalnie
"width": 839, // opcjonalnie (fallback wymiarów)
"height": 1190
}
5.3. DeepGaze — mapa uwagi (saliency)
Predykcja rozkładu uwagi wzrokowej; zwraca heatmapę zakodowaną base64.
POST http://{DEEPGAZE_HOST}/v1/predict-heatmap
Headers:
accept: application/json
Authorization: Bearer {TOKEN}
Body (multipart/form-data):
image = <plik>
Odpowiedź (wnioskowane):
{ "heatmap_b64": "<base64>",
"heatmap_mime": "image/png",
"width": 839, "height": 1190,
"model": "deepgaze..." }
→ mapuj na SaliencyMap{ source:"deepgaze", image_base64:heatmap_b64, mime:heatmap_mime }.
5.4. UNISAL — mapa uwagi (saliency, model porównawczy)
POST http://{UNISAL_HOST}/unisal/process-image?as_base64=true
Headers:
accept: application/json
X-API-Key: {TOKEN}
Body (multipart/form-data):
file = <plik>
Odpowiedź (wnioskowane):
{ "data": "<base64>", "mimetype": "image/jpeg" }
→ SaliencyMap{ source:"unisal", image_base64:data, mime:mimetype }.
5.5. ASM (asmModel) — mapy uwagi z warunkowaniem promptem
Model centralny: zwraca dwie mapy uwagi (szczegółową i ogólną), warunkowane tekstowym promptem osadzającym kontekst marketingowy.
POST http://{ASM_HOST}/asmModel/process-image
?prompt=Describe the image in the style of a polished marketing ad.
&as_raw_output=false
&max_new_tokens=100
Headers:
accept: application/json
X-API-Key: {TOKEN}
Body (multipart/form-data):
file = <plik>
Odpowiedź (wnioskowane):
{ "image_detailed": "<base64>",
"image_general": "<base64>",
"mimetype": "image/jpeg" }
→ dwa wpisy: SaliencyMap{source:"asm_detailed",...} oraz SaliencyMap{source:"asm_general",...}.
Uwaga: architektura ASM nie wynika z kontraktu — to wewnętrzny mikroserwis.
promptimax_new_tokenssugerują model multimodalny warunkowany językiem. Prompt potraktuj jako parametr konfigurowalny, nie stałą.
6. Orkiestracja
Logika sterująca (zastępuje przepływ narzędzia) — uruchom niezależne gałęzie równolegle, zachowując jedyną zależność LLaVA → Grounding DINO.
async def analyze(image_bytes) -> AnalysisResult:
img = preprocess(image_bytes) # bytes, base64, mime, w, h
async def detection_chain():
labels = await llava_object_types(img.bytes) # 5.1
labels_str = ", ".join(labels)
return await grounding_dino(img.bytes, labels_str) # 5.2
# gałęzie niezależne — równolegle
detection, deepgaze, unisal, asm = await gather(
detection_chain(), # łańcuch A (sekwencyjny wewnątrz)
deepgaze_heatmap(img.bytes), # B
unisal_saliency(img.bytes), # C
asm_saliency(img.bytes, PROMPT), # D
return_exceptions=True, # patrz sekcja 9
)
saliency = [
SaliencyMap("deepgaze", deepgaze.heatmap_b64, deepgaze.heatmap_mime),
SaliencyMap("unisal", unisal.data, unisal.mimetype),
SaliencyMap("asm_detailed", asm.image_detailed, asm.mimetype),
SaliencyMap("asm_general", asm.image_general, asm.mimetype),
]
return AnalysisResult(img, detection, saliency)
Zasady:
- Cztery gałęzie startują jednocześnie; całkowity czas ≈ czas najwolniejszej gałęzi.
- Punkt agregacji łączy wyniki dopiero, gdy potrzebne gałęzie się zakończą.
- Każdy artefakt wyjściowy zależy od konkretnego podzbioru wyników (sekcja 7) — można je generować, gdy tylko jego zależności są gotowe.
7. Warstwa prezentacji (artefakty wyjściowe)
Trzy artefakty. Można je renderować po stronie klienta (HTML/Canvas — jak w oryginale) lub serwerowo komponować obrazy (Pillow / sharp / canvas). Poniżej logika niezależna od wyboru.
7.1. Wizualizacja detekcji obiektów
Zależności: oryginał + DetectionResult.
- Dla każdego obiektu narysuj ramkę z
bbox_xyxy, podpis"{object_type} {score%}". - Kolor per typ obiektu (paleta cykliczna; ten sam typ = ten sam kolor).
- Pozycje przeliczaj na procenty wymiarów obrazu (
x1/width,y1/height, …), aby skalowały się responsywnie. - Opcjonalnie: filtry pokazujące/ukrywające typy, legenda, licznik obiektów.
7.2. Nakładka pojedynczej mapy uwagi
Zależności: oryginał + jedna SaliencyMap (np. DeepGaze).
- Heatmapa nałożona na oryginał z regulowaną przezroczystością (suwak 0–100%).
7.3. Porównanie map uwagi (siatka 2×2)
Zależności: oryginał + 4 mapy (deepgaze, unisal, asm_detailed, asm_general).
- Cztery kafelki, wspólny suwak intensywności, technika „inwersji" (7.4).
7.4. Algorytm „inwersji" heatmapy (blend luminancji)
Wspólna logika nakładek. Dla parametru t ∈ [0,1] (intensywność / pozycja suwaka):
# Z heatmapy licz luminancję (jasność uwagi) 0..1:
lum = (0.299*R + 0.587*G + 0.114*B) / 255
# Blend per kanał (RGB), per piksel:
out = orig * (1 - t) + (lum * 255) * t
t = 0→ czysty oryginał;t = 1→ maska uwagi w skali szarości (biel = wysoka uwaga, czerń = niska) → efekt „reflektora".- Wymaga zgodności rozdzielczości oryginału i heatmapy (w razie potrzeby przeskaluj heatmapę).
8. Konfiguracja i sekrety
Wynieś poza kod (zmienne środowiskowe / vault):
| Klucz | Opis |
|---|---|
LLAVA_HOST |
host usługi LLaVA |
GROUNDING_DINO_HOST |
host usługi Grounding DINO |
DEEPGAZE_HOST |
host usługi DeepGaze |
UNISAL_HOST |
host usługi UNISAL (w oryginale 1.208.108.242:58951) |
ASM_HOST |
host usługi ASM (w oryginale ten sam host co UNISAL) |
TOKEN |
poświadczenie (Bearer dla LLaVA/DINO/DeepGaze; X-API-Key dla UNISAL/ASM) |
ASM_PROMPT |
prompt warunkujący ASM (domyślnie marketingowy) |
MAX_OBJECTS |
limit detekcji (domyślnie 50) |
Dwa schematy autoryzacji:
Authorization: Bearer(LLaVA, Grounding DINO, DeepGaze) vsX-API-Key(UNISAL, ASM). Zaimplementuj per usługa.
9. Obsługa błędów i odporność
W oryginale węzły LLaVA, DeepGaze, UNISAL i ASM były ustawione na kontynuację mimo błędu — awaria pojedynczego modelu nie przerywała całości. Odtwórz to:
- Degradacja stopniowa: błąd jednej gałęzi → pomiń jej artefakt, zwróć pozostałe
(
return_exceptions/ per-tasktry/except). Nie przerywaj całej analizy. - Twarda zależność: jeśli LLaVA zawiedzie, Grounding DINO nie ma etykiet → pomiń detekcję (lub fallback: pusta lista / domyślne etykiety), reszta map uwagi działa dalej.
- Timeouty i retry: skończony timeout na każde wywołanie; ewentualny retry z backoffem dla błędów przejściowych (5xx / timeout).
- Walidacja odpowiedzi: sprawdzaj obecność kluczy (
labels,objects_bboxes,heatmap_b64,data,image_detailed/image_general) przed użyciem. - Zgodność wymiarów: przy blendzie/overlayu pilnuj zgodności rozdzielczości oryginału i map.
10. Proponowana dekompozycja modułów
| Moduł | Odpowiedzialność |
|---|---|
preprocess |
walidacja pliku, base64, mime, wymiary |
clients/ |
po jednym kliencie na usługę (LLaVA, GroundingDINO, DeepGaze, UNISAL, ASM); auth, timeout, parsowanie odpowiedzi |
orchestrator |
równoległe uruchomienie gałęzi, agregacja, obsługa błędów (sekcja 6, 9) |
models |
typy danych (sekcja 4) |
render/ |
generowanie artefaktów (overlay boxów, nakładka heatmapy, siatka 2×2 + blend) |
api/cli |
punkt wejścia: przyjmij obraz → zwróć AnalysisResult + artefakty |
Sugerowany stack: dowolny z natywną asynchronicznością i obsługą multipart oraz obrazów —
np. Python (FastAPI + httpx.AsyncClient + Pillow) lub Node (Fastify/Express + undici/fetch + sharp).
Renderowanie wizualizacji: serwerowo (kompozycja obrazu) albo zwrot danych + szablon kliencki.
11. Rozszerzenia (roadmapa)
Pierwotny projekt przewidywał dalsze etapy analizy uwagi (jeszcze niezaimplementowane):
- Mapa cieplna w interwałach czasowych (np. „30 s, 6 obrazów", „20 s → 0,5 s") — saliency rozłożona na przedziały czasu.
- Ścieżki fiksacji (scanpath) — przewidywana sekwencja ruchów oka.
- Mapa emocji — predykcja reakcji emocjonalnej na kreację.
Architektura z sekcji 6 jest na to przygotowana: dokładaj kolejne niezależne gałęzie do równoległej orkiestracji i nowe artefakty do warstwy prezentacji.
Specyfikacja odtworzona z istniejącego przepływu przetwarzania; kontrakty odpowiedzi oznaczone „wnioskowane" wymagają potwierdzenia z dokumentacją docelowych usług AI.