# Image Summarizer: Un motore RAG con un'immagine confusa limitata

<!-- category -- AI,Patterns,Architecture,LLM,DiSE -->
<datetime class="hidden">2026-01-06T17:00</datetime>

**Parti 1-3** descritta Constrizione Fuzziness come modello astrato. Questo articolo applica questi modelli ad un tubo di analisi dell'immagine funzionante che dimostra i principi in azione.

- **[CLI Tool](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.ImageSummarizer.Cli)** - Commando-interfaccia in linea per l'analisi delle immagini
- **[Core Library](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.DocSummarizer.Images)** - La biblioteca di analisi delle immagini sottostante

> NOTA: Stiamo ancora aggiustando il sistema. Ma c'è una versione di desktop come quella del CLI . Funziona molto bene ma ci sono anche dei margini per regolare l'affidamento.

### Guide per i lettori

Questo articolo serve a diversi scopi. Navigare per quello che ti interessa:

- **I modelli d'architettura** → Vedete "Architectura delle onde", "Contracto di segnaleM SK4
- **I dettagli dell'OCR** → Vedete [Parte 4.1: Pipeline OCR](/blog/constrained-fuzzy-image-ocr-pipeline) per una profonda crisi tecnica.
- **Usazione del CLI** → Jump to "The CLI: Using ItM SK3
- **Le caratteristiche del GUI** → Vedete la sezione "Desktop GUIM SK2
- **Implementazione** → Esempi di codici in tutto, la fonte completa su [GitHub](https://github.com/scottgal/lucidrag)

![La striscia di movimento](imagesumamrizerui.png?width=500&format=webp)

ImageSummarizer è un canale di ingestione RAG per immagini che extrae metadati strutturati, testoM SK1 sottotitoli, e segnali visivi usando una **architettura basata su onde-**. Il sistema si espande da un rapido analisi locale (FlorenceM SK2 ONNX) a Vision LLMs solo quando è necessario

**Principali principi:**

- Nessuna autonomia (i modelli non decidono mai i percorsi di esecuzione)
- No natural-language state M SK1signali sono digitatiMSC2 non prose)
- I modelli propongono segnali; la politica deterministica decide cosa rimane.

ImageSummarizer dimostra che i LLM multimodali possono essere usati senza arrendersi al determinismo. La regola fondamentale: **la probabilità propone, il determinismo persiste**.

> **Regole di progettazione**
> 
> - I modelli non consumano mai altri modelli' prose
> - Il linguaggio naturale non è mai stato.
> - L'escalazione è un limite deterministico.
> - Ogni output porta fiducia + provenienza

[![Licence: Non licenze](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)
[![Rilascio](https://img.shields.io/github/v/release/scottgal/lucidrag?label=release)](https://github.com/scottgal/lucidrag/releases)
[![Costruire](https://img.shields.io/github/actions/workflow/status/scottgal/lucidrag/release-imagesummarizer.yml?label=build)](https://github.com/scottgal/lucidrag/actions)
[![.NET](https://img.shields.io/badge/.NET-10.0-purple)](https://dotnet.microsoft.com/)

[toc]

---


## Cosa fa?

Il pipeline extrae metadati strutturati dalle immagini per i sistemi RAG. Con ogni immagine o animato GIF, produceM SK2

- Texto estratto (tre-OCR di livello orizzontaleM SK2 Tesseract → FlorenceMSC4 ONNX → Vision LLM fallbackMST6
- Palette di colore (computed,non è stato indovinatoM SK2
- Metriki di qualità (sharpness, blurM SK2 exposure )
- Classificazione del tipo (Photo, SketchscreenM SK2 Diagramma , MemeMSC4
- Analizza del movimento (per immagini animate)
- Copertina opzionale (Florenza-2 locale o Vision LLMM SK2 limitata dai fatti calcolati )
- Inserzioni semantiche (per la ricerca dei vettori)

La parola chiave è **strutturata**. Ogni output ha punteggi di fiduciaM SK1 attribuimento alla fonte, e indicatori di proveMST3 Nessun modello è la sola fonte della veritàMSC4

## Tre-Tier OCR Strategy

> **La profonda immersione**: Il tubo per l'OCR è abbastanza complesso da meritare il suo articolo. [Parte 4.1: I tre-Tier OCR Pipeline](/blog/constrained-fuzzy-image-ocr-pipeline) per la completa separazione tecnica compresa l'EAST, CRAFTM SK1 Real-ESRGAN , CLIPMSC4 e l'ottimizzazione delle piste di filmamentoMNK5

Il sistema usa una strategia di escalazione a tre livelli per l'estrazione del testo.

| Niveau | Metoda | Velocità | Costo SMK4 Perfetto per SSM5
| ----- | ------------------- | ------ | ----------- | ---------------------------- |
| **1** | **Tesseract** | ~50ms | gratis SMK3 pulitoM SK4 alto- testo contrasto M|
| **2** | **Florence-2 ONNX** |
| **3** | **Vision LLM** |

### Routing intelligente

**Detezione del testo di ONNX** ([L'AST](https://github.com/argman/EAST), [CRAFT](https://github.com/clovaai/CRAFT-pytorch), ~20-30ms) determina il percorso ottimaleM SK3

- **La strada più veloce**: Florence-2 solo (~100msM SK3
- **La strada BALANCED**: FlorenceM SK1 + Voto Tesseract SSK3ms)
- **La strada della qualità**: MultiM SK1analisi di un grafico + Vision LLM (~1-5s)

### Sostenere i modelli ONNX

- **[Real-ESRGAN](https://github.com/xinntao/Real-ESRGAN)**: 4× superM SK2 risoluzione per immagini di bassa qualità-Qualità MSC4msMSC5 gratisMST6
- **[CLIP](https://github.com/openai/CLIP)**: Immagazzinamenti semantici per la ricerca di immagini

**Risultato**: ~1.16GB di modelli locali ONNX che gestiscono 85%+ di immagini senza costi API.

---


## Vedete in azione

### Detezione del movimento & Analizzazione dell'animazione

![gatto sul divano](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.ImageSummarizer.Cli/demo-images/cat_wag.gif)

```bash
$ imagesummarizer demo-images/cat_wag.gif --pipeline caption --output text
Caption: A cat is sitting on a white couch.
Scene: indoor
Motion: MODERATE object_motion motion (partial coverage)
```

Le frasi di movimento vengono emettete solo quando sono supportate dalle misurazioni del flusso ottico e dai delti del fotogramma.

### Meme & Extrazione di sottotitoli

![Memo dell'ancorman](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.ImageSummarizer.Cli/demo-images/anchorman-not-even-mad.gif)

```bash
$ imagesummarizer demo-images/anchorman-not-even-mad.gif --pipeline caption --output text
"I'm not even mad."
"That's amazing."
Caption: A person wearing grey turtleneck sweater with neutral expression
Scene: meme
Motion: SUBTLE general motion (localized coverage)
```

Il sottotitolo-aware frame deduplication rileva i cambiamenti del testo in basso 25% dei frammentiM SK2 pesante pixel luminosi ( biancoMSC4 testo gialloMST5 più pesanteM ST6

### La tecnologia della striscia di un ramo

Per i GIF animati con sottotitoli, l'outil crea strisce di fotogramma orizzontali per l'analisi del Vision LLM. Tre modalità mirano a diversi tipi di usoM SK2

**Teksù-Si tratta solo della striscia** (NEW

Il modo più efficiente extrae solo le scatole di bottigliatura di testo, riduce drasticamente i costi del tocco:

![Teksù-Si tratta solo della striscia](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.DocSummarizer.Images/demo-images/anchorman-not-even-mad_textonly_strip.png)

```bash
$ imagesummarizer export-strip demo-images/anchorman-not-even-mad.gif --mode text-only
Detecting subtitle regions (bottom 30%)...
  Found 2 unique text segments
Saved text-only strip to: anchorman-not-even-mad_textonly_strip.png
  Dimensions: 253×105 (83% token reduction)
```

| Approco | Dimensioni | Tocconi | | | Costo ||
| -------------------- | ------------ | ------- | ------- |
| Cadre completi (10) | \3000×185 | | |
| strisce OCR (2 fotogrammi) | \600×185 || | | ~300 |
| **Teksù- solo striscia**  | **253×105** | **~50** | **Low** |

**Come funziona?**: OpenCV rileva le regioni di sottotitoli (estremità inferiore | 30%), soglia pixel luminosi |(bianca | МSK4 | testo giallo | ), | esstrae schede strette di bolle di bottiglia |M, | e deduplica a seconda dei cambiamenti del testo |m. | Il Vision LLM riceve solo le regioni del testo, | conservando tutti i contenuti di sottotitola eliminando pixel di fondo |.

**La striscia del modo OCR** ( solo cambiamenti di testo - 93 fotogrammi ridotta a M2 fotogramas):

![La striscia OCR](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.DocSummarizer.Images/demo-images/anchorman-not-even-mad_ocr_strip.png)

```bash
$ imagesummarizer export-strip demo-images/anchorman-not-even-mad.gif --mode ocr
Deduplicating 93 frames (OCR mode - text changes only)...
  Reduced to 2 unique text frames
Saved ocr strip to: anchorman-not-even-mad_ocr_strip.png
  Dimensions: 600x185 (2 frames)
```

**La striscia del modo di movimento** (keyframe per la deduzione del movimento):

![La striscia di movimento](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.DocSummarizer.Images/demo-images/cat_wag_motion_strip.png)

```bash
$ imagesummarizer export-strip demo-images/cat_wag.gif --mode motion --max-frames 6
Extracting 6 keyframes from 9 frames (motion mode)...
  Extracted 6 keyframes for motion inference
Saved motion strip to: cat_wag_motion_strip.png
  Dimensions: 3000x280 (6 frames)
```

Questo permette ai LLM della Vision di leggere tutti i sottotitoli in una sola chiamata API, migliorando drasticamente l'accuratezza dei memi e del contenuto sottotittato riducendo al minimo l'uso delle tochette.

### Perché non solo il titolo?

Questo batte "la cattura solo con un modello di frontiera" per lo stesso motivo che una radiografia XM SK2batte la narrazione : il modello non viene mai chiesto di riempire le bucheMSC4 Riceve un ledger chiusoMST5 colori misuratiMst6 movimento tracciatoM st7 frammenti di sottotitoli dedupatiMSt8 fiducia in OCRMstr9 e rende solo quello che il substrato già contieneMSST10 Quando GPTMsST11 la cattura un'immagineM SST12 è l'immaginazioneMSP14 quando ImageSummarizer lo faMSS15 è L'immiginazione di segnali già esistentiMSR16 la sommazione dei segnali esistenti

---


## L'architettura delle onde

Il sistema usa un **Pipeline basati su onde-** in cui ogni onda è un analizzatore indipendente che produce segnali digitati. **Le onde vengono eseguite in ordine prioritario (un numero più basso va avanti)**, e le onde più tardi possono leggere segnali da quelle precedentiM SK1

> **Ordonnanza di esecuzione**: Wave 10 funziona prima della Wave ♫50 ♫ funziona prima di la Wave \80. ♫ Numeri minori di priorità vengono executati prima nel pipeline ♫ . ♫

```mermaid
flowchart TB
    subgraph Wave10["Wave 10: Foundational Signals"]
        W1[IdentityWave - Format, dimensions]
        W2[ColorWave - Palette, saturation]
    end

    subgraph Wave40["Wave 40: Text Detection"]
        W9[TextLikelinessWave - OpenCV EAST/CRAFT]
    end

    subgraph Wave50["Wave 50: Traditional OCR"]
        W3[OcrWave - Tesseract]
    end

    subgraph Wave51["Wave 51: ML OCR"]
        W8[MlOcrWave - Florence-2 ONNX]
    end

    subgraph Wave55["Wave 55: ML Captioning"]
        W10[Florence2Wave - Local captions]
    end

    subgraph Wave58["Wave 58: Quality Gate"]
        W5[OcrQualityWave - Escalation decision]
    end

    subgraph Wave70["Wave 70: Embeddings"]
        W7[ClipEmbeddingWave - Semantic vectors]
    end

    subgraph Wave80["Wave 80: Vision LLM"]
        W6[VisionLlmWave - Cloud fallback]
    end

    Wave10 --> Wave40 --> Wave50 --> Wave51 --> Wave55 --> Wave58 --> Wave70 --> Wave80

    style Wave10 stroke:#22c55e,stroke-width:2px
    style Wave40 stroke:#06b6d4,stroke-width:2px
    style Wave50 stroke:#f59e0b,stroke-width:2px
    style Wave51 stroke:#8b5cf6,stroke-width:2px
    style Wave55 stroke:#8b5cf6,stroke-width:2px
    style Wave58 stroke:#ef4444,stroke-width:2px
    style Wave70 stroke:#3b82f6,stroke-width:2px
    style Wave80 stroke:#8b5cf6,stroke-width:2px
```

**Ordonnanza prioritaria** (la parte più bassa va primaM SK1 10 \→ | | 40\ | 5\ \ 50 \ |→ \

Questo è [MoM Fuzzy Constretto](/blog/constrained-mom-mixture-of-models) applicato all'analisi delle immagini: **molti proponenti pubblicano su un substrato condiviso.** (the `AnalysisContext`), e il risultato finale aggrega i loro segnaliM SK1

### Le onde chiave

- **Laonda di TextLikeliness** (NEWM SK1 OpenCV EAST/CRAFT Detezione del testo (~5-20msMSC4 determina le decisioni di routing
- **OcrWave**: Traditional Tesseract OCR per un testo pulito
- **MlOcrWave**: FlorenceM SK1 ONNX funziona localmente (~200ms), gestisce fonti stilizzati (Tier SSK5
- **Florence2Wave**: Insegnazione locale del ML quando il Vision LLM non è ' non è necessario
- **OcrQualityWave**: ScrissioneM SK1gate di controllo, determina il percorso dell'escalamento
- **VisionLlmWave**: CloudM SK1based Vision LLM, funziona solo quando le onde precedenti falliscono o segnano una bassa fiducia (Tier 3)

> **Nota sull'ordine delle onde**: I tre OCR **Terzi.** (Tesseract /FlorenceM SK2Vision LLM) sono i livelli di escalazione concettualeMSC4 Le onde individuali come Advanced OCR o Quality Gate sono **i raffinamenti.** all'interno di quei livelli, non sono livelli di escalazione separati—sfruttano controlli temporali di stabilizzazione e di qualità ,, respectivamente

---


## Il contratto di segnale

Ogni onda produce segnali usando un contratto standard.

```csharp
public record Signal
{
    public required string Key { get; init; }      // "color.dominant", "ocr.quality.is_garbled"
    public object? Value { get; init; }             // The measured value
    public double Confidence { get; init; } = 1.0;  // 0.0-1.0 reliability score
    public required string Source { get; init; }    // "ColorWave", "VisionLlmWave"
    public DateTime Timestamp { get; init; }        // When produced
    public List<string>? Tags { get; init; }        // "visual", "ocr", "quality"
    public Dictionary<string, object>? Metadata { get; init; }  // Additional context
}
```

Questa è la parte 2 contratto di segnale in azione. Le onde non parlano tra loro attraverso il linguaggio naturaleM SK2 pubblicano segnali tipificati nel contesto condiviso , e le onde sottocorrenti possono fare ricerche su questi segnaliMSC4

Notate che: `Confidence` è per -signaleM SK1 non per \-onde. Una singola onda può emmettere diversi segnali con una forza epistemica diversaMSC4ColorWaveMNK5 la lista dominante dei colori ha fiducia 1.0 ( calcolataMMK8 ma i percentuali di colore individuali usano la fiducia come fattore di peso per la sommificazione in avalitoMRK9

La fiducia qui significa *affidabilità per l'uso in aval.*, non la certezza matematica. I segnali deterministici sono riproducibiliM SK2 non fallibili -spellMSC4il controllo può essere sbagliato deterministicamente riguardo ai nomi appropriati

> **Causa del determinismo**: "Determinista" vuol dire che non c'è casualità di campionamento e risultati stabili per un dato periodo di runtime e configurazioneM SK3 I fornitori di GPU ONNX possono introdurre minor variazioni numericheMSC4 che sono accettabili per le decisioni di routingMNK5 Il contratto di segnale (valoriMMK7 logica dell'escalamentoMS) rimane completamente deterministicoM.

---


### Taxonomia del segnale OCR

Per evitare confusione, qui' è il canoniconamespace di segnale OCR usato nel sistemaM SK2

| Key di Signale | Source | Description
| ------------------------------- | ---------------------- | ---------------------------------------------- |
| `ocr.text` | Tesseract  (Tier
| `ocr.confidence` | Tesseract
| `ocr.ml.text` | FlorenceM SK1 (Tier 2) \| ML OCR single-frame SSK6
| `ocr.ml.multiframe_text` | FlorenzaM SK1 Tier SSK3 \| Multi-frame GIF OCR | preferenziata per le animazioni
| `ocr.ml.confidence` | Florenza-2 | FlorenceM SK3 punteggio di fiducia |
| `ocr.quality.spell_check_score` | OcrQualityWave | Scritto deterministicoM SK2 rapporto di controllo |
| `ocr.quality.is_garbled` | OcrQualityWave | Signale d'escalamento boolean |
| `ocr.vision.text` | VisionLlmWave  (Tier
| `caption.text` | VisionLlmWave | Copertina descriptiva (separata dall'OCR

**Una distinzione importante**: `ocr.vision.text` Si tratta di un sistema basato sull'informazione. **Extrazione di testo** (OCRM SK1 mentre `caption.text` Si tratta di un sistema basato sull'informazione. **descrizione della scena** (captioning). Entrambi possono provenire dalla stessa chiamata Vision LLMM SK2 ma servono a scopi diversi .

**Priorità della selezione finale del testo** (la più alta alla più bassa

1. `ocr.vision.text` (Vision LLM OCR
2. `ocr.ml.multiframe_text` (Florenza-2 GIFM SK2
3. `ocr.ml.text` (Florence-2singleM SK2frameMSC3
4. `ocr.text` (Tesseract)

---


## L'interfaccia delle onde

Ogni onda implementa un semplice interfaccia:

```csharp
public interface IAnalysisWave
{
    string Name { get; }
    int Priority { get; }           // Lower number = runs earlier (10 before 50 before 80)
    IReadOnlyList<string> Tags { get; }

    Task<IEnumerable<Signal>> AnalyzeAsync(
        string imagePath,
        AnalysisContext context,    // Shared substrate with earlier signals
        CancellationToken ct);
}
```

L'informazione figura nella parte dispositiva. `AnalysisContext` E' l'elemento più importante. **Spazio di consenso** da parte 2. Canne di onde:

- Leggere segnali dalle onde precedenti: `context.GetValue<bool>("ocr.quality.is_garbled")`
- Accès cached intermedii risultati: `context.GetCached<Image<Rgba32>>("ocr.frames")`
- Aggiungere nuovi segnali che le onde a valle possono consumare.

---


## ColorWave: La fondazione deterministica

ColorWave fa funzionare prima (priority 10) e calcola fatti che limitano tutto il resto:

```csharp
public class ColorWave : IAnalysisWave
{
    public string Name => "ColorWave";
    public int Priority => 10;  // Runs first (lowest priority number)
    public IReadOnlyList<string> Tags => new[] { "visual", "color" };

    public async Task<IEnumerable<Signal>> AnalyzeAsync(
        string imagePath,
        AnalysisContext context,
        CancellationToken ct)
    {
        var signals = new List<Signal>();

        using var image = await LoadImageAsync(imagePath, ct);

        // Extract dominant colors (computed, not guessed)
        var dominantColors = _colorAnalyzer.ExtractDominantColors(image);
        signals.Add(new Signal
        {
            Key = "color.dominant_colors",
            Value = dominantColors,
            Confidence = 1.0,  // Reproducible measurement
            Source = Name,
            Tags = new List<string> { "color" }
        });

        // Individual colors for easy access
        for (int i = 0; i < Math.Min(5, dominantColors.Count); i++)
        {
            var color = dominantColors[i];
            signals.Add(new Signal
            {
                Key = $"color.dominant_{i + 1}",
                Value = color.Hex,
                Confidence = color.Percentage / 100.0,
                Source = Name,
                Metadata = new Dictionary<string, object>
                {
                    ["name"] = color.Name,
                    ["percentage"] = color.Percentage
                }
            });
        }

        // Cache the image for other waves (no need to reload)
        context.SetCached("image", image.CloneAs<Rgba32>());

        return signals;
    }
}
```

La Vision LLM riceve più tardi questi colori come **Constrizioni**. Non dovrebbe pretendere che l'immagine abbia "rossi vibranti" se ColorWave ha calcolato che il colore dominante è bluMSC3 e se lo faM SK4 la contraddizione può essere rilevata e può essere rifiutata in avalanche.

---


## OcrQualityWave: La porta dell'escalazione

Questo è il luogo dove [Fuzzinesse limitata](/blog/constrained-fuzziness-pattern) brilla. OcrQualitàWave è la **Constrainer** che decide se scaldare a Vision LLM: costoso

```csharp
public class OcrQualityWave : IAnalysisWave
{
    public string Name => "OcrQualityWave";
    public int Priority => 58;  // Runs after OCR waves
    public IReadOnlyList<string> Tags => new[] { "content", "ocr", "quality" };

    public async Task<IEnumerable<Signal>> AnalyzeAsync(
        string imagePath,
        AnalysisContext context,
        CancellationToken ct)
    {
        var signals = new List<Signal>();

        // Get OCR text from earlier waves (canonical taxonomy)
        string? ocrText =
            context.GetValue<string>("ocr.ml.multiframe_text") ??  // Florence-2 GIF
            context.GetValue<string>("ocr.ml.text") ??             // Florence-2 single
            context.GetValue<string>("ocr.text");                  // Tesseract

        if (string.IsNullOrWhiteSpace(ocrText))
        {
            signals.Add(new Signal
            {
                Key = "ocr.quality.no_text",
                Value = true,
                Confidence = 1.0,
                Source = Name
            });
            return signals;
        }

        // Tier 1: Spell check (deterministic, no LLM)
        var spellResult = _spellChecker.CheckTextQuality(ocrText);

        signals.Add(new Signal
        {
            Key = "ocr.quality.spell_check_score",
            Value = spellResult.CorrectWordsRatio,
            Confidence = 1.0,
            Source = Name,
            Metadata = new Dictionary<string, object>
            {
                ["total_words"] = spellResult.TotalWords,
                ["correct_words"] = spellResult.CorrectWords
            }
        });

        signals.Add(new Signal
        {
            Key = "ocr.quality.is_garbled",
            Value = spellResult.IsGarbled,  // < 50% correct words
            Confidence = 1.0,
            Source = Name
        });

        // This signal triggers Vision LLM escalation
        if (spellResult.IsGarbled)
        {
            signals.Add(new Signal
            {
                Key = "ocr.quality.correction_needed",
                Value = true,
                Confidence = 1.0,
                Source = Name,
                Tags = new List<string> { "action_required" },
                Metadata = new Dictionary<string, object>
                {
                    ["quality_score"] = spellResult.CorrectWordsRatio,
                    ["correction_method"] = "llm_sentinel"
                }
            });

            // Cache for Vision LLM to access
            context.SetCached("ocr.garbled_text", ocrText);
        }

        return signals;
    }
}
```

La decisione sull'escalamento è **determinista.**: se il punteggio di controllo dello spelling < 50%, emette un segnale che attiva la visione LLM. Niente giudizio probabilisticoM SK4 No \" forse dovremmo chiedere al LLM

### Escalazione in azione

![Arse Biscuits](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.DocSummarizer.Images/demo-images/arse_biscuits.gif)

```bash
$ imagesummarizer demo-images/arse_biscuits.gif --pipeline caption --output text
OCR: "ARSE BISCUITS"
Caption: An elderly man dressed as bishop with text reading "arse biscuits"
Scene: meme
```

L'OCR ha ricevuto il testo; Vision LLM ha fornito un contesto di scena. Ogni onda contribuisce a quello che è buono.

---


## VisionLlmWave: Il Propositore Constretto

La onda Vision LLM funziona solo quando i segnali precedenti lo indicano.

```csharp
public class VisionLlmWave : IAnalysisWave
{
    public string Name => "VisionLlmWave";
    public int Priority => 50;  // Runs after quality assessment
    public IReadOnlyList<string> Tags => new[] { "content", "vision", "llm" };

    public async Task<IEnumerable<Signal>> AnalyzeAsync(
        string imagePath,
        AnalysisContext context,
        CancellationToken ct)
    {
        var signals = new List<Signal>();

        if (!Config.EnableVisionLlm)
        {
            signals.Add(new Signal
            {
                Key = "vision.llm.disabled",
                Value = true,
                Confidence = 1.0,
                Source = Name
            });
            return signals;
        }

        // Check if OCR was unreliable (garbled text)
        var ocrGarbled = context.GetValue<bool>("ocr.quality.is_garbled");
        var textLikeliness = context.GetValue<double>("content.text_likeliness");
        var ocrConfidence = context.GetValue<double>("ocr.ml.confidence",
            context.GetValue<double>("ocr.confidence"));

        // Only escalate when: OCR failed OR (text likely but low OCR confidence)
        // Models never decide paths; deterministic signals do (no autonomy)
        bool shouldEscalate = ocrGarbled ||
                              (textLikeliness > 0.7 && ocrConfidence < 0.5);

        if (shouldEscalate)
        {
            var llmText = await ExtractTextAsync(imagePath, ct);

            if (!string.IsNullOrEmpty(llmText))
            {
                // Emit OCR signal (Vision LLM tier)
                signals.Add(new Signal
                {
                    Key = "ocr.vision.text",  // Vision LLM OCR extraction
                    Value = llmText,
                    Confidence = 0.95,  // High but not 1.0 - still probabilistic
                    Source = Name,
                    Tags = new List<string> { "ocr", "vision", "llm" },
                    Metadata = new Dictionary<string, object>
                    {
                        ["ocr_was_garbled"] = ocrGarbled,
                        ["escalation_reason"] = ocrGarbled ? "quality_gate_failed" : "low_confidence_high_likeliness",
                        ["text_likeliness"] = textLikeliness,
                        ["prior_ocr_confidence"] = ocrConfidence
                    }
                });

                // Optionally emit caption (separate signal)
                var llmCaption = await GenerateCaptionAsync(imagePath, ct);
                if (!string.IsNullOrEmpty(llmCaption))
                {
                    signals.Add(new Signal
                    {
                        Key = "caption.text",  // Descriptive caption (not OCR)
                        Value = llmCaption,
                        Confidence = 0.90,
                        Source = Name,
                        Tags = new List<string> { "caption", "description" }
                    });
                }
            }
        }

        return signals;
    }
}
```

Il punto di vista chiave: **Il testo di Vision LLM ha fiducia 0.95, non 1.0**. E'' migliore di un OCR rottoM SK2 ma è ancora probabilistico . L'agregazione a cascata lo saMSSK5 PSK6Perché CSM7 Predefinito primaMST8 configurato per modelloMSC9pipelineMSV10 registrato nella configurazioneMSM11 Il valore esatto conta meno che *avere* Un valore che non è't 1.0.)

---


## Il foglio: Sintesi limitata

L'informazione figura nella parte dispositiva. `ImageLedger` Accumula segnali in sezioni strutturate per il consumo in avalito. Questo è [Dragging Contexto](/blog/constrained-fuzzy-context-dragging) applicato all'analisi delle immagini:

```csharp
public class ImageLedger
{
    public ImageIdentity Identity { get; set; } = new();
    public ColorLedger Colors { get; set; } = new();
    public TextLedger Text { get; set; } = new();
    public MotionLedger? Motion { get; set; }
    public QualityLedger Quality { get; set; } = new();
    public VisionLedger Vision { get; set; } = new();

    public static ImageLedger FromProfile(DynamicImageProfile profile)
    {
        var ledger = new ImageLedger();

        // Text: Priority order - corrected > voting > temporal > raw
        ledger.Text = new TextLedger
        {
            ExtractedText =
                profile.GetValue<string>("ocr.final.corrected_text") ??  // Tier 2/3 corrections
                profile.GetValue<string>("ocr.voting.consensus_text") ?? // Temporal voting
                profile.GetValue<string>("ocr.full_text") ??             // Raw OCR
                string.Empty,
            Confidence = profile.GetValue<double>("ocr.voting.confidence"),
            SpellCheckScore = profile.GetValue<double>("ocr.quality.spell_check_score"),
            IsGarbled = profile.GetValue<bool>("ocr.quality.is_garbled")
        };

        // Colors: Computed facts, not guessed
        ledger.Colors = new ColorLedger
        {
            DominantColors = profile.GetValue<List<DominantColor>>("color.dominant_colors") ?? new(),
            IsGrayscale = profile.GetValue<bool>("color.is_grayscale"),
            MeanSaturation = profile.GetValue<double>("color.mean_saturation")
        };

        return ledger;
    }

    public string ToLlmSummary()
    {
        var parts = new List<string>();

        parts.Add($"Format: {Identity.Format}, {Identity.Width}x{Identity.Height}");

        if (Colors.DominantColors.Count > 0)
        {
            var colorList = string.Join(", ",
                Colors.DominantColors.Take(5).Select(c => $"{c.Name}({c.Percentage:F0}%)"));
            parts.Add($"Colors: {colorList}");
        }

        if (!string.IsNullOrWhiteSpace(Text.ExtractedText))
        {
            var preview = Text.ExtractedText.Length > 100
                ? Text.ExtractedText[..100] + "..."
                : Text.ExtractedText;
            parts.Add($"Text (OCR, {Text.Confidence:F0}% confident): \"{preview}\"");
        }

        return string.Join("\n", parts);
    }
}
```

Il ledger è il **L'ancora** in termini di CFCD. Porta avanti quello che è la selezione sopravvissutaM SK1 e la sintesi LLM deve rispettare questi fatti.

---


## La decisione sull'escalazione

Avete visto la logica dell'escalamento in due posti. `OcrQualityWave` emissioni *i segnali.* sulla qualità; `EscalationService` applicce *politica.* attraverso quei segnali. Questa è separazione intenzionale:

- **Wave-escalazione locale**: Ogni onda emette informazioni sul suo dominio (eM SK2g., "L'OCR è sconvolto
- **Escalazione del livello di servizio-**: `EscalationService` Aggrega segnali e applica limiti globali.

L'informazione figura nella parte dispositiva. `EscalationService` Mette tutto insieme. Implementa il modello della parte 1 **substrato → proposer → constrainer**:

```csharp
public class EscalationService
{
    private bool ShouldAutoEscalate(ImageProfile profile)
    {
        // Escalate if type detection confidence is low
        if (profile.TypeConfidence < _config.ConfidenceThreshold)
            return true;

        // Escalate if image is blurry
        if (profile.LaplacianVariance < _config.BlurThreshold)
            return true;

        // Escalate if high text content
        if (profile.TextLikeliness >= _config.TextLikelinessThreshold)
            return true;

        // Escalate for complex diagrams or charts
        if (profile.DetectedType is ImageType.Diagram or ImageType.Chart)
            return true;

        return false;
    }
}
```

Ogni decisione di escalazione è **determinista.**: le stesse entrate , gli stessi sogliamenti, la stessa decisioneM SK3 Nessun giudizio LLM nella logica dell'escalamentoMSC4

---


## La Visione LLM Prompt: Constrizioni di prova

Quando il Vision LLM funziona, riceve i fatti calcolati come restrizioni:

```csharp
private static string BuildVisionPrompt(ImageProfile profile)
{
    var prompt = new StringBuilder();

    prompt.AppendLine("CRITICAL CONSTRAINTS:");
    prompt.AppendLine("- Only describe what is visually present in the image");
    prompt.AppendLine("- Only reference metadata values provided below");
    prompt.AppendLine("- Do NOT infer, assume, or guess information not visible");
    prompt.AppendLine();

    prompt.AppendLine("METADATA SIGNALS (computed from image analysis):");

    if (profile.DominantColors?.Any() == true)
    {
        prompt.Append("Dominant Colors: ");
        var colorDescriptions = profile.DominantColors
            .Take(3)
            .Select(c => $"{c.Name} ({c.Percentage:F0}%)");
        prompt.AppendLine(string.Join(", ", colorDescriptions));

        if (profile.IsMostlyGrayscale)
            prompt.AppendLine("  → Image is mostly grayscale");
    }

    prompt.AppendLine($"Sharpness: {profile.LaplacianVariance:F0} (Laplacian variance)");
    if (profile.LaplacianVariance < 100)
        prompt.AppendLine("  → Image is blurry or soft-focused");

    prompt.AppendLine($"Detected Type: {profile.DetectedType} (confidence: {profile.TypeConfidence:P0})");

    prompt.AppendLine();
    prompt.AppendLine("Use these metadata signals to guide your description.");
    prompt.AppendLine("Your description should be grounded in observable facts only.");

    return prompt.ToString();
}
```

Il Vision LLM non dovrebbe affermare "colori vibranti " se abbiamo calcolato la scala grigia-se lo faM SK3la contraddizione è rilevabileMSC4 Non dovrebbe affermar " dettagli acutiMska6 se noi abbiamo calcolata una bassa varianza LaplacianMske7se l'ha fattoMске8 possiamo rifiutare il risultatoMsko9 **Il substrato deterministico restringe il risultato probabilistico.**.

Queste restrizioni riducono l'allucinazione ma non la possono eliminare-i richiedi sono suggerimenti,non garantisconoM SK2 L'eseguimento reale avviene in aval via weighting di fiducia e selezione del segnale . Il richiedo è una strataMST4 l'architettura è l'altraM ST5

---


## Priorità del testo di output

Quando si extrae il testo finale, il sistema usa un rigoroso ordine di priorità:

```csharp
static string? GetExtractedText(DynamicImageProfile profile)
{
    // Priority chain using canonical signal names (see OCR Signal Taxonomy above)
    //   1. Vision LLM OCR (best for complex/garbled)
    //   2. Florence-2 multi-frame GIF (temporal stability)
    //   3. Florence-2 single-frame (stylized fonts)
    //   4. Tesseract (baseline)

    var visionText = profile.GetValue<string>("ocr.vision.text");
    if (!string.IsNullOrEmpty(visionText))
  ocally (confidence 0.85-0.90, no cost)
- **Tesseract voting**: Reliable for clean text (confidence varies, deterministic)
- **Raw Tesseract**: Baseline fallback (confidence < 0.7 for stylized fonts)

The priority order encodes this knowledge. Florence-2 sitting between Vision LLM and Tesseract provides a "sweet spot" for most images—better than traditional OCR, cheaper than cloud Vision LLMs.

Note: this function selects *one* source, but the ledger exposes *all* sources with their confidence scores. Downstream consumers can-and should-inspect provenance when the domain requires it. The priority order is a sensible default, not a straitjacket.

---

## Selection and Conflict Resolution

The priority chain above is the current implementation-a simple fallback. But the architecture supports adding rejection rules as config-driven policy. Here's the pattern for contradiction detection (not yet implemented, but the signals exist to support it):

```csharp
// Pattern: Contradiction detection as policy rules
public static class SelectionPolicy
{
    public static string? SelectTextWithConstraints(DynamicImageProfile profile)
    {
        var visionText = profile.GetValue<string>("vision.llm.text");
        if (!string.IsNullOrEmpty(visionText))
        {
            // Rule: Reject if Vision claims text but deterministic signals say no text
            var textLikeliness = profile.GetValue<double>("content.text_likeliness");
            if (textLikeliness < _config.TextLikelinessThreshold && visionText.Length > 50)
            {
                // Contradiction detected - log and fall through
                profile.AddSignal(new Signal
                {
                    Key = "selection.vision_rejected",
                    Value = "text_likeliness_contradiction",
                    Confidence = 1.0,
                    Source = "SelectionPolicy",
                    Metadata = new Dictionary<string, object>
                    {
                        ["text_likeliness"] = textLikeliness,
                        ["vision_text_length"] = visionText.Length,
                        ["threshold"] = _config.TextLikelinessThreshold
                    }
                });
                // Fall through to OCR sources
            }
            else
            {
                return visionText;
            }
        }

        // Continue with priority chain...
        return profile.GetValue<string>("ocr.voting.consensus_text")
            ?? profile.GetValue<string>("ocr.full_text");
    }
}
```

Lo stesso schema si applica ad altri tipi di segnale:

- **Contraddizione di colore**: rifiutare la copertina che dice "rossi vibrantiM SK2 se `color.is_grayscale` E' vero.
- **Contraddizione di Sharpness**: Resetta la legenda che dice " dettagli precisi" se `quality.sharpness` < soglia
- **Tipo contraddizione**: rifiutare la copertina che dice " una personaM SK2 se `content.type` È un diagramma con grande fiducia.

Le proprietà chiave della strata di selezione:

- **La catena di priorità**: Ogni fonte ha un ordine di fallback definito, non adM SK2 selezione hoc
- **Porta di qualità in arrivo**: l'OCR è accettato quando la porta deterministica dice che ' non è rotturata
- **Punto di estensione**: Le regole di contraddizione sono guidate da config- e versionate come tutte le altre politiche.
- **Il percorso di revisione**: Le respingeri emetteno segnali con valori e limiti osservati.

Questo è il punto in cui "determinismo persisteM SK1 diventa meccanicamente vero . L'LLM propone; regole deterministiche che decidono se accettare o meno.

---


## Configurazione del tubo di pipeline JSON

I tubi sono completamente configurabili tramite JSON, rendendo la composizione delle onde esplicita e verificabile:

```json
{
  "name": "advancedocr",
  "displayName": "Advanced OCR (Default)",
  "description": "Multi-frame temporal OCR with stabilization and voting",
  "estimatedDurationSeconds": 2.5,
  "accuracyImprovement": 25,
  "phases": [
    {
      "id": "color",
      "name": "Color Analysis",
      "priority": 100,
      "waveType": "ColorWave",
      "enabled": true
    },
    {
      "id": "simple-ocr",
      "name": "Simple OCR",
      "priority": 60,
      "waveType": "OcrWave",
      "earlyExitThreshold": 0.98
    },
    {
      "id": "advanced-ocr",
      "name": "Advanced Multi-Frame OCR",
      "priority": 59,
      "waveType": "AdvancedOcrWave",
      "dependsOn": ["simple-ocr"],
      "parameters": {
        "maxFrames": 30,
        "ssimThreshold": 0.95,
        "enableVoting": true
      }
    },
    {
      "id": "quality",
      "name": "OCR Quality Assessment",
      "priority": 58,
      "waveType": "OcrQualityWave",
      "dependsOn": ["advanced-ocr"]
    }
  ]
}
```

I limiti di partenza iniziali lasciano passare le onde costose quando le onde economiche hanno già raggiunto un alto grado di fiducia. Questa è la parte della gestione del budget 1.

---


## L'Auto Pipeline: Intelligent Routing

L'informazione figura nella parte dispositiva. `auto` pipeline implements smart routing based on image characteristics, selecting the optimal processing path:

```
Image Analysis (OpenCV ~5-20ms)
    │
    ├── Is animated (>1 frame)?
    │   └── ANIMATED route
    │       ├── Has subtitle regions? → Text-only strip extraction
    │       ├── Minimal text? → FAST (Florence-2 only)
    │       └── Motion significant? → Motion analysis
    │
    ├── Has text regions (OpenCV detection)?
    │   ├── High contrast, clean text → FAST route (Florence-2, ~100ms)
    │   ├── Moderate confidence → BALANCED route (Florence-2 + Tesseract, ~300ms)
    │   └── Low confidence → QUALITY route (Multi-frame + Vision LLM, ~1-5s)
    │
    ├── Is chart/diagram (type detection)?
    │   └── QUALITY route → Vision LLM caption
    │
    └── Default → FAST route (Florence-2 caption)
```

### Rendimento delle rotte

| Route | Triggers When | Processing S| Time M| Costo R|
| -------- | ------------------------------------------------ | ----------------------------- | ------ | ------------ |
| FAST | testo semplice, contrasto altoM SK3 caratteri standard MSC4 FlorenceMSC5 solo S| R~100ms M| bassa Plocale
| BALANCED | Texte normaliM SK2 Confidenza moderata | Florenza-2 M+ Voto Tesseract R| | | ~300ms || Basso Plocale
| QUALItà | ChartsM SK2 diagrammi, fonti stilizzatiMSC4 bassa fiducia | MultiMNK6frame SNK7 Vision LLM M| S~1-5s R| Medio IAPIMMK12 \|
| ANIMATED | GIF con sottotitoli | Texto-only strip S+ filmtrip M| D~2-3s P| Medium R(API) | |

### Esempio reale: Selezione automatica della rotta

```bash
$ imagesummarizer anchorman-not-even-mad.gif --pipeline auto --output visual
[Route selection...]
  Image: 300×185, 93 frames
  Text detection: 15 regions found (bottom 30%)
  Subtitle pattern: DETECTED
  → Selected ANIMATED route (text-only filmstrip)

[Processing...]
  MlOcrWave: Extracted 10 frames → 2 unique text segments
  Text-only strip: 253×105 (83% token reduction)
  VisionLlmWave: Processing filmstrip...

[Results - 2.3s total]
Text: "I'm not even mad." + "That's amazing."
Caption: A person wearing grey turtleneck sweater with neutral expression
Scene: meme
Motion: SUBTLE general motion
```

La decisione di routing è deterministica e registrata nei segnali per l'audit:

```json
{
  "routing": {
    "selected_route": "ANIMATED",
    "reason": "subtitle_pattern_detected",
    "text_regions": 15,
    "frames": 93,
    "decision_time_ms": 18
  }
}
```

---


## Il CLI: che lo usa

### Usazione basilare

```bash
# Use auto pipeline (smart routing - recommended)
imagesummarizer meme.gif --pipeline auto

# Fast local caption with Florence-2 ONNX (~200ms)
imagesummarizer photo.jpg --pipeline florence2

# Best quality: Florence-2 + Vision LLM
imagesummarizer complex-diagram.png --pipeline florence2+llm

# Extract text only (three-tier OCR)
imagesummarizer screenshot.png --pipeline advancedocr

# Motion analysis for GIFs
imagesummarizer animation.gif --pipeline motion

# Process a directory with visual output
imagesummarizer ./photos/ --output visual
```

### Raccolte dei segnali

Chiedete solo i segnali di cui avete bisogno usando pre-collectioni definite:

```bash
# Minimal metadata (fast)
imagesummarizer image.png --signals "@minimal"

# Alt text for accessibility
imagesummarizer image.png --signals "@alttext"

# Motion analysis
imagesummarizer animation.gif --signals "@motion"

# Full analysis
imagesummarizer image.png --signals "@full"

# Custom wildcard patterns
imagesummarizer image.png --signals "color.dominant*, ocr.text, motion.*"
```

| Collezione | Signali | | | Usage Case
| ---------- | --------------------------------------- | ------------------ |
| `@minimal` | identitàM SK1*, qualitàM SK1 acutezza | Solo un profilo veloce |
| `@alttext` | caption.textM SK2 ocrMSC3text\, color+.dominante* | Accessibilità  |
| `@motion` | movimento.*,identitàM SK1frame_cett.
| `@full` | Tutti i segnali | Analizio completo |
| `@tool` | Subset ottimizzato | MCP/automatizzazione |

### Reale JSON Output

```bash
$ imagesummarizer princess-bride.gif --output json
```

```json
{
  "image": "princess-bride.gif",
  "duration_ms": 1838,
  "waves_executed": ["ColorWave", "OcrWave", "AdvancedOcrWave", "VisionLlmWave"],
  "text": {
    "value": "You keep using that word.\nI do not think it means what you think it means.",
    "source": "ocr.voting.consensus_text",
    "confidence": 0.95
  },
  "escalation": {
    "triggered": true,
    "reason": "text_likeliness_above_threshold",
    "threshold": 0.4,
    "observed": 0.67
  },
  "signals": {
    "color.dominant_1": { "value": "#1a1a2e", "confidence": 1.0 },
    "ocr.quality.spell_check_score": { "value": 0.82, "confidence": 1.0 },
    "ocr.quality.is_garbled": { "value": false, "confidence": 1.0 },
    "motion.type": { "value": "static", "confidence": 0.95 }
  }
}
```

Ogni campo ha una provenienza. `escalation` I mostri di blocchi *Perché?* Il Vision LLM si chiamava ..

### L'analisi del movimento

![Alan Shrug](https://raw.githubusercontent.com/scottgal/lucidrag/main/src/Mostlylucid.ImageSummarizer.Cli/demo-images/alanshrug_opt.gif)

```bash
$ imagesummarizer demo-images/alanshrug_opt.gif --pipeline motion
Motion: SUBTLE general motion (localized coverage)
Direction: up-down
Magnitude: 0.23
```

### Il modo interattivo

```bash
$ imagesummarizer
ImageSummarizer Interactive Mode
Pipeline: advancedocr | Output: auto | LLM: auto
Commands: /help, /pipeline, /output, /llm, /model, /ollama, /models, /quit

Enter image path (or drag & drop): F:\Gifs\meme.gif
Processing...
I'm not even mad. That's amazing.

Enter image path: /llm true
Vision LLM: enabled

Enter image path: /model minicpm-v:8b
Vision model: minicpm-v:8b
```

### La GUI del Desktop

Per l'esplorazione visiva, l'applicazione desktop fornisce:

- **Drag & drop interface**: Abbattere immagini per l'analisi istantanea
- **Live log dei segnali**: Watch waves execute in real life-time with confidence coloring
- **Indicatori di stato del modello**: Il sistema di luce stradale (🟢 pronto, 🟡 TraduzioneM SK4 | | 🔴 fallito
- **Preview di GIF animato**: Vedete la generazione di filmtrip e l'estrazione dei frammenti.
- **Inspectore del segnale**: Click any signal to see full provenance and metadata
- **Il selettore del tubo**: Switch between autoM SK1florence2/qualityMSC3motion mode
- **Opzioni di esportazione**: Copia i segnali come JSON, risparmia le strisce di pellicolaM SK2 testo d'export

L'interfaccia grafica del desktop dimostra l'architettura visiva— potete vedere esattamente quali onde sono andate in funzione, quali segnali hanno emesso , e come sono state prese le decisioni di routingM SK3 Perfetto per capire il sistema o per debuggere i pipelines personalizzati

Il CLI espone tutta la complessità come semplici opzioni. Si possono cambiare i tubi di tubature, modelliM SK2 e formati di output senza capire l'architettura delle onde .

---


## Dove si presentano i modelli

| Parte | Pattern | Implementazione di ImageSummarizer S|
| ---- | ---------------------------------------------------------------- | ----------------------------------------------------------------------- |
| 1    | [Fuzzinesse limitata](/blog/constrained-fuzziness-pattern) | ColorWave calcola i fatti; VisionLlmWave li rispetta |
| 2    | [MoM Fuzzy Constretto](/blog/constrained-mom-mixture-of-models) | Pubblico di diverse onde per l'analisiContextoM SK1 Coordinate dell'orchestratore Wave |
| 3    | [Dragging Contexto](/blog/constrained-fuzzy-context-dragging) | ImageLedger accumula caratteristiche salientiM SK1 SignalDatabase caches results |

Lo stesso schema. Domaino diversoM SK1 La stessa regola: **la probabilità propone, il determinismo persiste**.

---


## Quello che otteniamo

- **RaG-produzione pronta**: JSON strutturato con punteggi di fiducia
- **Local-processo iniziale**: FlorenceM SK1 ONNX funziona localmente (~200ms), nessun costo API per la maggior parte delle immagini
- **Routing intelligente**: Il tubo automatico seleziona il percorso ottimale (FASTM SK2BALANCED/QUALITYMSC4
- **Effizienza dei simboli**: testoM SK1 solo le strisce raggiungono una riduzione di tocco 30× per i sottotitoli GIF
- **Decisioni verificabili**: Ogni escalazione ha una ragione esplicita con provenienza
- **Modello-agnostico**: Swap Ollama per OpenAI o Anthropic senza cambiare l'architettura
- **Calcolato secondo il contenuto**: Stessa immagine = la stessa analisi, anche se rinominata ( Cache di SQLiteM SK4 S2-10 battute msMSC6
- **La GUI del Desktop**: DragM SK1and-drop interface with live signal visualization
- **MCP server mode**: Integrare con qualsiasi LLM che supporta il Protocollo di Contexto Modello (Claude DesktopM SK2 etc.)
- **L'API basata su Signal-**: Demande solo quello di cui avete bisogno usando schemi o collezioni di carte selvatiche

## Quanto costa?

- **Coste cognitive superiori**: Dovreste capire il contratto del segnale , le priorità delle onde M SK2 e la logica dell'escalamento prima di scrivere una sola onda . Questo punisce il pensiero slancio MSC4
- **Disziplina dello spettro**: Ogni chiave di segnale ha bisogno di una definizione chiara . Ogni punteggio di fiducia ha bisogno della logica. Non si può dare la manoM SK3onda "il modello lo calcolaMSC5
- **Per-complexità delle onde**: Ogni onda ha la propria configurazioneM SK1 casi a bordo, e modalità di infezione . Il debugging avviene al livello delle ondeMSC4 non al livello del tubo di tubaturaMNK5
- **Superficie di test**: Più componenti significa più test . Togliere il contestoM SK2 Assert the signals, verificare i percorsi di escalazioneMSC4
- **Investizioni anticipate**: Definete le ondeM SK1 i segnali , e la struttura del ledger prima di vedere i risultati. La ricompensa arriva più tardi

Questo non è il percorso veloce. È il percorso affidabileM SK1 vale la pena se avete bisogno di una comprensione dell'immagine verificabile su larga scala; l'overkill se avete solo bisogno di sottotitoli per una galleria fotografica .

---


## Mode di fallimento e come questo li affronta

| Mode di fallimento | Cosa succede | Come viene gestito S'
| ------------------------------ | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Noisy GIF** | Frame jitterM SK1 Artifatti di compressione | Stabilizzazione temporanea + Deduplicazione SSIM SSK4 Consenso di voto ESK5 testoESC6estrazione solo a strisce EESC7
| **OCR restituisce i rifiuti.** | Tesseract fallisce sulle fonti stilizzate | Scrabble-Check gate rileva < MESK4 corretto S→ si espande a FirenzeM SK6 \→ Vision LLM se ancora debole ♫|
| **I costi elevati dell'API** | Troppo tante chiamate LLM da cloud Vision | Florence-2 ONNX gestisce 80%+ localmente S~200msM SK5 testoMSC6 solo le strisce riducono i tokens SSK7 per i GIF | |
| **Alucinazioni visive** | LLM afferma che il testo non è ' non c'è | I segnali permettono di individuare le contraddizioni ( lo schema mostrato qui SSK4 i consumatori in avalismo possono confrontare`vision.llm.text` contro `content.text_likeliness` |
| **I cambiamenti del pipeline nel tempo** | New waves addedM SK1 thresholds adjusted | Content-hash caching |+ full provenance in every signal | + version tracking |
| **Il modello non restituisce nulla.** | Tempo spento o risposta vuota della Vision LLM | Chain di Fallback: Vision LLS → FlorenceM SK4 SSK5 Votazione Tesseract ♫→ OCR crudo ♫ ; ordine prioritario assicura una graziosa degradazione ♫

Ogni modo di fallimento ha una risposta deterministica. Nessuna degradazione silenziosa.

---


## Il quadro più grande: Multi-Rag grafico modulare

> **Contexto importante**: ImageSummarizer è il **Il tubo di ingestione dell'immagine** per l'ecosistema LucidRAG.

Questo articolo si concentra sull'estrazione di segnali strutturati dalle immagini.

- **[DocSummarizer](https://github.com/scottgal/lucidrag)** - Analyse strutturata del documento PDFs, marcaturaM SK3 codice
- **[DataSummarizer](https://github.com/scottgal/lucidrag)** - Profilazione dei dati tabulari (CSVM SK2 database)
- **ImageSummarizer** (Questo articoloM SK1 - Analitica delle immagini e dell'animazione

Quando si attaccano insieme. **LucidRAG** (ci sarà presto!), queste tre pipelines permettono di **multi-modal graph RAG**:

```
Document → DocSummarizer → Structured signals
    ↓
Images → ImageSummarizer → Structured signals
    ↓
Data → DataSummarizer → Structured signals
    ↓
    ↓ (all signals)
    ↓
LucidRAG Graph Builder → Multi-modal knowledge graph
    ↓
Query → Multi-modal retrieval + constrained generation
```

**Perché questo è importante?**: La RAG tradizionale tratta le immagini come gocce opache che vengono sottotittateM SK1 Multi- grafico modico La RAg tratta le foto come **Source di segnali della prima classe-** con le relazioni tra i caratteri e il testo, datiM SK1 e altre immagini. Gli stessi principi del determinismoMNK3 scala diversaMMK4

La scala del modello: se si possono estrarre segnali strutturati dalle immagini (questo articoloM SK2 documenti ([DocSummarizer](/blog/building-a-document-summarizer-with-rag)), e dati ([DataSummarizer](/blog/datasummarizer-how-it-works)), si può costruire un grafico di conoscenza dove ogni nodo ha una provenienza e ogni bordo ha dei punteggi di fiducia.

**Arrive presto.**: Integrazione LucidRAG completa che mostra come questi tubi si compongono in multi-questioni di RAG a grafico modicoM SK2 Gli stessi principi architettonici , substrato di segnale unificatoMSC4

---


## Conclusione

L'architettura ha una struttura: ogni onda è indipendente, ogni segnale viene digitato , ogni escalazione è deterministaM SK3 FlorenceMSC4 fornisce un rapido analisi localeMST5 Vision LLM gestisce casi complessiMSSK6 ma nessuna opera senza limitiMSL7 i segnali deterministici ancorano sempre il risultatoMSM8

Dalla pubblicazione iniziale dell'articolo, il sistema si è evoluto significativamente:

- **Florence-2 Integrazione ONNX** Riduce i costi e la latenza dell'API (~200ms local vs ~1-5s cloud)
- **testo-solo filmtrip** Si ottiene una riduzione del tocco 30× per i sottotitoli GIF.
- **Pipeline automatica** Seleziona il percorso ottimale basato sulle caratteristiche dell'immagine.
- **Raccolte di segnali** semplificare i casi di uso comune (@alttext, @motionM SK3 |
- **La GUI del Desktop** fornisce il drag-and-drop analysis con la visualizzazione del segnale dal vivo.

Solo il tubo di OCR—con i suoi tre varianti-espansione dei livelliM SK2multi--eletazione di fotogrammi ,ottimizzazione delle strisce di pellicola,, e del testo,-estrazione solo di strisce,M SK7è diventato abbastanza complesso da poter meritare un articolo dettagliato. [Integrazione dell'OCR nella visione](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/vision-ocr-integration.md) Guidanza per il completo blocco tecnico.

Se si può fare questo per le immagini—il tipo di input più complicato, con il rumore dell'OCRM SK2 caratteri stilizzati , fotogrammi animatiMST4 e allucinazioniMSSK5capitali propensiMSC6si può fare per ogni componente probabilisticoMSM7

Che's Constrizione Fuzziness in pratica . Non un modello astratoM SK2 Code di lavoro.

---


## Ressource

### Repositorio

- **[LucidRAG Repository](https://github.com/scottgal/lucidrag)** - Il codice sorgente completo

### CLI Tool

- **[ImageSummarizer CLI](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.ImageSummarizer.Cli)** - Command-line tool for image analysis
- **[CLI README](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.ImageSummarizer.Cli/README.md)** - InstallationM SK1 Usazione, e configurazione
- **[Immagini demo](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.ImageSummarizer.Cli/demo-images)** - Esempi di GIF e strisce di fotogramma mostrati in questo articolo

### Core Library

- **[DocSummarizer.Images](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.DocSummarizer.Images)** - Core image analysis library
- **[Library README](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/README.md)** - Documentazione APIM SK1 architettura delle onde, e guida di integrazione
- **[Guide per l'architettura](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/architecture.md)** - WavesM SK1 Signale, escalationMSC3 caching
- **[Documentazione Pipeline](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/pipelines.md)** - AutoMSC1 bilanciato, qualitàM SK3 florenzaMST4llm
- **[Integrazione dell'OCR nella visione](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/vision-ocr-integration.md)** - RoutingM SK1 filmtrips, economy token
- **[L'analisi del movimento](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/motion.md)** - Extrazione di frammenti GIF, Detezione del movimento
- **[Riferimento ai segnali](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/signals.md)** - catalogo dei segnali , collezioni, sintassi delle carte selvatiche

### Article connessi

- [DocSummarizer](/blog/building-a-document-summarizer-with-rag) - Il tubo di analisi del documento usando modelli simili.
- [DataSummarizer](/blog/datasummarizer-how-it-works) - Profilazione dei dati con lo stesso determinismo - primo approccio

---


## La serie

| Parte | Tipo | Asse S|
| ---- | ------------------------------------------------------------------------- | ------------------------------- |
| 1    | [Fuzzinesse limitata](/blog/constrained-fuzziness-pattern) | Componente unica |
| 2    | [MoM Fuzzy Constretto](/blog/constrained-mom-mixture-of-models) | Numerosi componenti |
| 3    | [Dragging Contexto](/blog/constrained-fuzzy-context-dragging) | Tempo / memoria |
| 4    | **Intelligenza dell'immagine (questo articolo)**                                     | **L'architettura delle onde, modelli** |
| 4.1  | [Il Pipeline Three-Tier OCR](/blog/constrained-fuzzy-image-ocr-pipeline) | OCRM SK1 Modelli ONNX, filmtrips |

**Più avanti**: Parte 5 mostrerà come ImageSummarizer [DocSummarizer](/blog/building-a-document-summarizer-with-rag), e [DataSummarizer](/blog/datasummarizer-how-it-works) comporsi in grafico multi-modal RAG con LucidRAG.

Tutte le parti segueno la stessa invariante: **Componenti probabilistice propose; sistemi deterministici persistono**.