# Image Summarizer: En begränsad fuzzy Image RAG Engine

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

**delar 1-3** beskriven begränsad oförklarhet som ett abstraktt mönster. Detta artikel applicerar dessa mönste på en arbetsbildanalys som demonstrerar principerna i praktiken

- **[CLI-verktyg](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.ImageSummarizer.Cli)** - Kommandot - gränssnitt för bildanalys
- **[Kernbiblioteket](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.DocSummarizer.Images)** - Den underliggande bildanalysbiblioteket

> NOTET: Ändå tända systemet. Men det finns nu en version för ', som även CLIs version. It works PRETTY well but some edges to smooth out

### Läsareführer

Detta artikel tjänar flera syften. Navigera till vad du är intresserad av

- **Arkitekturmuster** → Se  "Vavelarkitekturen
- **OCR-detailler** → Se [Del 4.1: OCR Pipeline](/blog/constrained-fuzzy-image-ocr-pipeline) för djupa tekniska nedbrytningar
- **CLI-användning** → Spring till " CLI: s apparat
- **GUI-fenskaper** → Se sektionen "Desktop GUI
- **Implementering** → Kodexexempler över hela , full source på [GitHub](https://github.com/scottgal/lucidrag)

![Motion Stripp](imagesumamrizerui.png?width=500&format=webp)

ImageSummarizer är en RAG-inspegningskanal för bilder som extraherar strukturerade metadata, ,, text, ,, captioner och visuella signaler med hjälp av **architecture based wave-**. Systemet skalar upp från snabb lokal analys (Florence-2 ONNXM SK3 till Vision LLMs endast när det behövs .

**Nyckelprinciper**

- Ingen självständighet (modeller bestämmer aldrig utdragsvägar)
- Inget naturliga-språks tillstånd (signaler är inskrivna , inte prosaM SK3
- Modell föreslår signaler ; deterministisk policy bestämmer vad som förblir

ImageSummarizer visar att multimodella LLM kan användas utan att ge upp determinism. **sannolikhet föreslår , determinism förblir**.

> **Designregler**
> 
> - Modeller konsumerar aldrig andra modeller
> - Naturspråk är aldrig ett tillstånd
> - Escalation är deterministiska trösklar
> - Varje utgång bär på förtroende + provenance

[![Licensen : Olicenctioner](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)
[![frigöra](https://img.shields.io/github/v/release/scottgal/lucidrag?label=release)](https://github.com/scottgal/lucidrag/releases)
[![Att bygga](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]

---


## Vad det gör

Pipelinen extraherar strukturerade metadata från bilder för RAG-system.

- Utvunnet text (dree-tier OCRM SK2 Tesseract → FlorenceMska4 ONNX mska5 Vision LLM fallbackM Ska6
- Farbpalette (beräknat, inte gisst
- Kvalite mätningar ( skarphet , svaghet, exponering
- Typklassificering (Foto, Synkronis , Diagram , Meme )
- Rödselanalys ( för animerade bilderM SK1
- Optionellt undertecknande (Florens -2 lokal eller Vision LLM, begränsad av beräknings faktaM SK3
- Semantiska inbäddar ( för vektorsökningen)

Det viktigaste ordet är **strukturerad**. Varje utgång har tillförlitlighetsvärdena , källans antagning, , och bevispunkter,. Ingen modell är den enda källan till sanning,

## Tre-Tier OCR-strategi

> **Deep Dive**: Pipelinet för OCR är tillräckligt komplex för att äga en egen artikel [Del 4.1: De tre-Tier OCR Pipeline](/blog/constrained-fuzzy-image-ocr-pipeline) för den kompletta tekniska uppsättningen inklusive EAST, CRAFTM SK1 Real-ESRGANMska3 CLIPMske4 och optimering av filmsträngarnaM Ska5

Systemet använder en escalationsstrategi på tre nivåer för textextraktion.

| Niveau | Methode | | | Tempo | | | kostnaderna | МSK4 | bäst för |
| ----- | ------------------- | ------ | ----------- | ---------------------------- |
| **1** | **Tesseract** | ~50ms | | | Gratis | | | Rent | МSK4 | högt |- | motstridiga text
| **2** | **Florence-2 ONNX** | ~200ms | | | Gratis | МSK3 | Stiliserade fonter | , | inga API-kostnader |
| **3** | **Vision LLM** | ~1-5s | | | $0.001-0.01 | | | komplext

### Intelligent ruttering

**Detektorn för text** ([Öst](https://github.com/argman/EAST), [KRATT](https://github.com/clovaai/CRAFT-pytorch), ~20-30msM SK2 bestämmer den optimala vägen

- **FAST-väg**: Florensen -2 bara (~100ms)
- **BALANCED-väg**: FlorenceM SK1 + Tesseract-röstning
- **QUALITY-väg**Multi- -frameanalys Vision LLM (~1-5 s )

### stödja ONNX-modeller

- **[Real-ESRGAN](https://github.com/xinntao/Real-ESRGAN)**: ♫ 4× super ♫ ♫
- **[CLIP](https://github.com/openai/CLIP)**: Semantiska inbäddar för bildsökningar (~100msM SK2 gratis)

**Resultat**: ~1.16GB av lokala ONNX-modeller som hanterar 85%+ av bilder utan API-kostnader

---


## Se det i praktiken

### Motion Detection & Animationsanalys

![Katt på soffan](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)
```

Rörningsfraser släpps ut endast när de stödjers av optiska flöde mätningar och ramdeltas.; annars faller systemet tillbaka till neutrala beskrivare.

### Meme & Tilltving av undertitel

![Anchorman-memen](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)
```

Den undertiteln-medveten ramduplikering detekterar textförändringar i botten 25% av bilderna , viktande ljusa pixels | ( | vit | МSK4 | gul text |) | mer kraftigt |

### Frame Strip Technology

För animerade GIFs med subtitler, skapar redskapet horisontella ramsträngar för Vision LLM-analysen . Tre moder fokuserar på olika användningsområden:

**Text-Omnär Strep** (NEW

Den mest effektiva metoden extraherar bara textbubblade lådor, dramatiskt minskar tokenskostnader:

![Text-Omnär Strep](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)
```

| tillvägagångspunkt
| -------------------- | ------------ | ------- | ------- |
| Hela tallrikar (10)
| OCR-stripp | | (2 | frammänder | ) | m| | M600×185 |M| |m~300 | мSK7 | mellan
| **Text- endast fläck**  | **253×105** | **~50** | **låg** |

**Hur det fungerar**: OpenCV detekterar subtitrets områden | ( | botten |30%), | tröskeln ljusa pixeler | МSK3 | vit | / | gul text |), | extraherar smala bångboxar | , | och duplicerar baserat på textförändringar ♫ . | Vision LLM får bara textregionen ♫ , | bevarar all subtitretts innehåll medan den eliminerar bakgrundspixeln ♫.

**OCR-läger** (tydliga ändringar i texten | | - | МSK2 | rader reducerade till |

![OCR-stripp](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)
```

**Motion Mode-stripp** (keyframes för rörelsesuppfattningar

![Motion Stripp](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)
```

Detta låter Vision LLMs läsa alla undertitel i en enda API sändning.

### Varför inte bara tända det?

Det slår " bara att döma upp det med en gränsmodell " av samma anledning som ett X-ray slår på berättelsen : modellen blir aldrig tillfrågad att fylla på luckor M SK4 Den får en stängd ledger, -, mätda färger, ,, spårade rörelser,,, avvikta subtitret frammarmor, MSC8, OCR-förtroende, M SK9 och bara återskapa det som substratet redan innehåller, MSL10, när GPT, MLS11, dömer upp en bild, Msl12, det, MKL13, gissningen, MCL14, när ImageSummarizer gör, MNL15, det och MKL16, sammanfattande signaler som redan finns, MHL17.

---


## Architecturen i vågen

Systemet använder **våg---baserad bränsleledning** där varje våg är en oberoende analysator som producerar utskrivna signaler **vågor sätter igång i prioritära ordning. ( lägre talet kör först.**, och senare vågor kan läsa signaler från tidigare

> **Tilrättelse**: Plötsligt ♫ ♫ 10 rinner innan plötslig ♫

```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
```

**Prioriterad ordning** ( lägre löper först): 10 ♫ ♫ → ♫

Det här är [Begränsad Fuzzy MoM](/blog/constrained-mom-mixture-of-models) tillämpat på bildanalys: **flera proposer publicerar till ett gemensamt substrat** (the `AnalysisContext`), och den slutgiltiga utgången aggregerar sina signaler

### Nyckelvågor

- **Textliknande våg** (NEW
- **OcrWave**: Traditionell Tesseract OCR för ren text (Tier 1)
- **MlOcrWave**: Florence-2 Runner lokalt på ONNX (~200msM SK3 hanterar stiliserade fonter |
- **Florence2Sål**: Lokala ML-captionering när Vision LLM inte är
- **Ocrkvalitetsvåg**: Spell -kontroll portaal, bestämmer stegeringsväg
- **VisionLlmWave**: Cloud, -baserade Vision LLM, ,, funkar bara när tidigare vågor misslyckas eller signalerar lågt självförtroende.

> **Beteckning om vågsortering**: De tre OCR: n **våningar** (Tesseract /Florence-2/Vision LLMM SK3 är de konceptuella nivåerna för eskalationenMSC4 Individuella vågor som Advanced OCR eller Quality Gate är **raffineringar** within those tiers , not separate escalation levels—they perform temporal stabilization and quality checks

---


## Signalkontraktet

Varje våg producerar signaler med hjälp av en standardiserad kontrakt

```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
}
```

Detta är den delen 2 Signalkontraktet i praktiken .vågor pratar inte med varandra genom naturlig språk . De publicerar utskrivna signaler till den de delar med sig av i sammanhanget M SK3 och nedströmsvågor kan ställa frågor om dessa signaler

Kom ihåg att `Confidence` är per-signalM SK1 inte per -welle. En enda våg kan skicka ut flera signaler med olika epistemiska styrkorMska4färgvågenMske5 dess dominerande färglista har självförtroendet M Ska6 | | Mska7 beräknat Mska8 men individuella färgprocent använder självför troendet som en viktfaktor för nedåtgående sammanfattning

Tillit här betyder *tillförlitlighet för nedströmsanvändning*, inte matematisk säkerhet . Deterministiska signaler är återskapbara , inte felaktiga M SK3 spelttonning MSC4 kontroll kan vara deterministiskt fel på korrekta namn

> **Bestämning om determinism**:, ", Deterministiskt, M SK2, betyder att det inte finns någon slumpmässig sampling och stabila resultat för en given lopptid och konfiguration.

---


### OCR-signaltaksonom

För att undvika förvirringar

| Signal nyckeln | källan ♫ ♫ | ♫ Beskrywing ♫
| ------------------------------- | ---------------------- | ---------------------------------------------- |
| `ocr.text` | Tesseract (Tier 1) | råddig enkel M-frame OCR MMA5
| `ocr.confidence` | Tesseract
| `ocr.ml.text` | FlorenceM SK1 (Tier ♫ ♫ 2) ♫
| `ocr.ml.multiframe_text` | Florensen -2 (Tier | | 2) | | | Multi | МSK5 | frambild GIF OCR | | föredrars för animationer |
| `ocr.ml.confidence` | Florenz1 | Florence3 självförtroende siffra
| `ocr.quality.spell_check_score` | OcrQualityWave
| `ocr.quality.is_garbled` | OcrQualityWave
| `ocr.vision.text` | VisionLlmWave
| `caption.text` | VisionLlmWave

**En viktig skillnad**: `ocr.vision.text` är **extraktion av text** (OCRM SK1 medan `caption.text` är **scenbeschreibung** (captioning). Båda kan komma från samma Vision LLM sändning, men till olika syften.

**Den slutgiltiga textselektionens prioritet** (höjsta till lägsta

1. `ocr.vision.text` (Vision LLM OCR
2. `ocr.ml.multiframe_text` (Florens
3. `ocr.ml.text` (Florence
4. `ocr.text` (Tesseract)

---


## Wave-gränssnittet

Varje våg implementerar en enkel gränssnitt

```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);
}
```

Den `AnalysisContext` är **konsensussutrymme** från en del 2.vågor kan

- Att läsa signaler från tidigare vågor: `context.GetValue<bool>("ocr.quality.is_garbled")`
- Zugriff på cachede mellanresultat: `context.GetCached<Image<Rgba32>>("ocr.frames")`
- Lägg till nya signaler som nedströmsvågor kan konsumera

---


## ColorWave: Det deterministiska fundamentet

ColorWave kör först (prioriteet 10) och räknar fakta som begränsar allt annat

```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;
    }
}
```

Vision LLM får senare dessa färger som **begränsningar**. Den borde inte hävda att bilden har ♫ " ♫ kraftfulla röda ♫" ♫ om ColorWave räknat ut att den dominerande färgen är blå ♫

---


## OcrQualityWave: Escalation Gate

Det här är [Begränsad otydighet](/blog/constrained-fuzziness-pattern) strålar. OcrQualityWave är **konstrainer** som bestämmer om man ska skala upp till dyr Vision LLM:

```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;
    }
}
```

Beslutet om escalation är **deterministisk**: om stavningskontrollsvärdet ♫ < ♫ ♫50%, ♫ avger en signal som utlöser syn LLM ♫

### Escalation i aktion

![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
```

OCR fick texten

---


## VisionLlmWave: Begränsade författare

Vision LLM-vågen sätter igång endast när tidigare signaler visar att den är möjlig.

```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;
    }
}
```

Den viktigaste insikten **Vision LLM text har förtroende 0.95, inte 1.0**. Det är bättre än förruttnade OCR, men det är fortfarande sannolikhetsmässigt, .. Den nedgående aggregationen vet detta. *att ha* en värde som är't 1.0.)

---


## Ledgern : Begränsad syntes

Den `ImageLedger` samlar in signaler i strukturerade sektioner för nedströmsförbrukning [Kontext dragning](/blog/constrained-fuzzy-context-dragging) tillämpat på bildanalys:

```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);
    }
}
```

Ledgern är **ankar** i CFCD termer . Den för vidare vad som överlevt urvalen, och LLM-synthesen måste respektera dessa fakta

---


## Beslutet om att kliva

Ni har sett eskalationslogik på två ställen. `OcrQualityWave` utsläpper *signaler* om kvalitet; `EscalationService` gäller *policy* över de signalerna . Det här är avsiktligt separerande:

- **Wave-lokal escalation**: Varje våg släpper ut fakta om dess domain.
- **Service---nivåns upphöjning**: `EscalationService` aggregerar signaler och applicerar globala trösklar

Den `EscalationService` sammanfogar det hela. Den implementerar delen 1 mönster **substrat → förespråkare → konstrainer**:

```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;
    }
}
```

Varje escalationsval är **deterministisk**: samma ingångar , samma tröskeln , samma beslut M SK3 Inga LLM-bedömande i eskalationslogiken

---


## Vision LLM Prompt: Evidensbegränsningar

När Vision LLM körs, får den beräknade fakta som begränsningar.

```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();
}
```

Vision LLM borde inte hävda "kraftiga färger " om vi räknade gråskalan - om det gör det M SK3 motsägelserna är upptäckbara Mska4 Det borde inte behaupta ♫ " skarpa detaljer Mske6 om man räknade låga Laplacian-varianser **deterministisk substrat begränsar den probabilistiska utgången**.

Dessa begränsningar minskar hallucinationen men inte eliminerar den.

---


## Utgångsteksprioriteet

När man extraherar den slutgiltiga texten

```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");
    }
}
```

Samma mönster gäller andra typer av signaler:

- **Färger motsägelser**: Refusera undertiteln som påstår " kraftfulla röda punkter `color.is_grayscale` är sant
- **Sharpness motsägelse**: Refrigera captionen som påstår " skarpa detaljer `quality.sharpness` < tröskel
- **Typ motsägelse**: Refusera undertiteln som påstår " en person `content.type` är Diagramm med hög trovärdighet

De viktigaste egenskaperna hos den valskivan:

- **Prioritetskedjan**: Varje källa har en definierad fallback ordning
- **Kvalite-grind uppströms**: OCR accepteras när det deterministiska spåret säger att den är inte förruttrad (< 50% rätt ord spolar uppvärmning
- **Längsvinkel**: motsägelsreglerna är config-driven och versionerade som alla andra regler
- **Revideringsspår**: Motsägelser släpper ut signaler med observerade värden och trösklar

Det är här som "determinism förblir kvar " blir mekaniskt sant M SK2 LLM föreslår ; deterministiska regler som bestämmer om man ska acceptera

---


## JSON-pingelinkonfiguration

Pipeliner är fullt konfigurierbara via JSON, vilket gör att vågsstrukturen är tydlig och kontrollbar :

```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"]
    }
  ]
}
```

tidiga utgångsgränser låter dyra vågor hoppa över när billiga strömmar redan har uppnått hög trovärdighet.

---


## Det automatiserade Pipelinet: Intelligent ruttering

Den `auto` pipeline implementerar smart ruttering baserat på bilder

```
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)
```

### Route-presterande

| Router | | | Triglar när || | Bearbetande || | Timm | МSK4 | kostnaderna | |
| -------- | ------------------------------------------------ | ----------------------------- | ------ | ------------ |
| FAST | Enkel text, hög kontrastMSG3 standardfonts MSG4 FlorenzMSC5 bara МСG6 MSG7ms msG8 lågt | |  | lokal | MSG10 | msG11
| BALNED | Normal text, måttlig självförtroende
| KVALITY | Diagrammar | , | Diagramer | МSK3 | Stiliserade fonts |, | lågt självförtroende ♫ | | Multi | - | ram |+ | Vision LLM ♫ ♫ | ♫
| ANIMATED | GIF-bilder med undertitel | | Text | - | enkel stripp | МSK4 | film | 5 | 6 | 7 | mellan | 8 | API | 9 | 10

### Ett verkligt exempel: Automatisk Route Selection

```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
```

Rutingstillståndet är deterministiskt och registrerad i signaler för audit.

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

---


## The CLI: Using It

### Grundanvändning

```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
```

### Signalinsamlingar

Säg bara de signaler du behöver genom att använda förutfattade samlingar-

```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.*"
```

| Kollektion | Signaler
| ---------- | --------------------------------------- | ------------------ |
| `@minimal` Identitet*, kvalitetM SK1 skarphet | Bara snabbprofil |
| `@alttext` | undertiteln . text* | tillgänglighet  |
| `@motion` | rörelse*,identitet.framemöjlighet, _koll, ♫ ♫ | ♫ Animationsanalys ♫
| `@full` | Alla signaler | Hela analysen |
| `@tool` | Optimiserad undergrupp | MCP/automation |

### Den riktiga JSON utgången

```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 }
  }
}
```

Varje fält har provenance. Den `escalation` blockshows *varför* Vision LLM kallades ".".

### rörelseanalys

![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
```

### Interaktiva Modus

```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
```

### Desktop GUI

För visuella utforskningar, erbjuder datorapplikationen

- **Drag & drop-gränssnitt**: Släpp bilder till direkt analys
- **Livsignallogg**: Uhrvågor sätter igång i realtid -tid med självförtroende färg
- **Modellens statusindikatorer**: trafikljussystem | | (🟢 | Ready |
- **En animerad GIF-version**: Se filmspår generering och ram extraktion
- **Signalinspektor**: klicka på vilket signal som helst för att se hela provenansen och metadata
- **Pipeline-selektor**: byter mellan automatiska /blomma2/kvalitéM SK3rörelsemodi
- **Export options**: Kopiera signaler som JSON , spara filmsträngar

Det skrivbords GUI demonstrerar arkitekturen visuellt— du kan se exakt vilka vågor som gick igång , vilka signaler de skickade ut , och hur rutteringsbesluten fattades

CLI visar alla komplexiteten som enkla alternativ.

---


## Var mönsterna syns

| del | mönster | | | Implementering av ImageSummarizer
| ---- | ---------------------------------------------------------------- | ----------------------------------------------------------------------- |
| 1    | [Begränsad otydighet](/blog/constrained-fuzziness-pattern) | ColorWave bearbetar fakta; VisionLlmWave respekterar dem |
| 2    | [Begränsad Fuzzy MoM](/blog/constrained-mom-mixture-of-models) | Flera vågor publiceras i analys Kontexten ; Bandorchesterkoordinater | |
| 3    | [Kontext dragning](/blog/constrained-fuzzy-context-dragging) | ImageLedger samlar upp salienta egenskaperM SK1 Signaldatabas-cacheresultat |

Samma mönster **sannolikhet föreslår , determinism förblir**.

---


## Vad du får

- **RAG-ready utgång**: Strukturerad JSON med självförtroende poäng
- **Lokalt-first bearbetande**: FlorenceM SK1 ONNX kör lokalt (~200ms), inga API-kostnader för de flesta bilder
- **Intelligent ruttering**: Automatisk pipeline väljer den optimala vägen
- **Symboleffektivitet**: Text
- **Rättsliga beslut**: Varje eskalation har ett tydligt skäl med ursprung
- **Modell-agnostisk**: Swap Ollama till OpenAI eller Anthropic utan att ändra arkitektur
- **Cachéd av innehåll**: Samma bild
- **Desktop GUI**: Drag
- **MCP-server-läger**: Integrera med vilken LLM som supporterar Model Context Protocol som helst.
- **Signal-baserad API**: Säg bara vad du behöver med hjälp av wildcard mönster eller samlingar

## Vad det kostar

- **Kognitiv överhead**: Du måste förstå signalkontraktet , vågprioriteer , och eskaleringslogi innan du skriver en enda våg M SK3 Det bestraffar sluppig tankesätt MSC4
- **Specdisciplin**: Varje signalnyckled behöver en klar definition . Varje självförtroendes poäng behöver en resonemang
- **Per-vågkomplexitet**: Varje våg har sin egen konfiguration , randföreställningar , och felläger M SK3 Debugging sker på vågnivån MSC4 inte på ledningsnivån
- **Försökande yta**: Fler komponenter innebär fler tester . Förflytta kontexten , bekräfta signalerna M SK3 kontrollera upphöjdhetens vägar
- **Tillgångsinvesteringar**: Du definierar vågor , signaler M SK2 och ledgerstruktur innan du ser resultaten . Belöningen kommer senare

Det här är inte den snabbaste vägen. Den är den tillförlitliga vägen . Det är värt det om du behöver en kontrollbar bild förståelse på skala

---


## Misslyckandensmodi och hur det löser dem

| Missbruksmöjlighet | | | Vad händer || | Hur det går |
| ------------------------------ | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Skrämmande GIF** | Framsjitter , kompressionsartefakter | | | Tillfällig stabilisering | МSK3 | SSIM-duplikation |
| **OCR återvänder skräp** | Tesseract misslyckas med stiliserade fonter | Spell-kontrollgrann detekterar | | < | МSK4 | korrekt | → | uppskrider till Florenz | LLM om syn än är dålig |
| **Höga API-kostnader** | Alltför många cloud Vision LLM-sändningar | | | Florensen |-2 | ONNX löser | 80%+ | lokalt ♫ ~200 | ms | МSK5 | text | - | bara fläckar reducerar token |30× | för GIFs |
| **Synhallucinationer** | LLM säger att texten som inte är ' finns där ♫ | ♫ Signaler gör det möjligt att upptäcka motsägelser ♫`vision.llm.text` mot `content.text_likeliness` |
| **Pipelineförändringar över tid** | Nya vågor lagts till , tröskelnjusterade | | | innehåll | МSK3 |hash-caching | + | full provenance in every signal |+ | version tracking |
| **Modellen ger inget tillbaka** | Vision LLM upptimening eller tom respons | Fallback-skedja | | : | Vision LML | → | Florence | МSK4 |→ | Tesseract-röstning |

Varje felläger har en deterministisk respons. Ingen tyst nedbrytning.

---


## Den större bilden : Multi-Modal Graph RAG

> **En viktig kontext**: ImageSummarizer är **bildinspegningsrör** för LucidRAG ekosystem.

Detta artikel fokuserar på att extrahera strukturerade signaler från bilder.

- **[DocSummarizer](https://github.com/scottgal/lucidrag)** - Strukturerad dokumentanalys
- **[DataSummarizer](https://github.com/scottgal/lucidrag)** - Tabulardataprofilering (CSVM SK2 databaser)
- **ImageSummarizer** (den här artikelnM SK1 - Bild- och animationsanalys

När de kopplas ihop med **LucidRAG** ( "Kom snart" !), dessa tre banor möjliggör **multi-modal graf 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
```

**Varför är detta viktigt?**: Traditionella RAG behandlar bilder som osynliga fläckar som får captioning **första-klass signaler** med tiffade kopplingar till texten, data , och andra bilder. Samma deterministiska principer

Patternskalan är: : om du kan extrahera strukturerade signaler från bilderna.[DocSummarizer](/blog/building-a-document-summarizer-with-rag)), och data ([DataSummarizer](/blog/datasummarizer-how-it-works)), kan du bygga en kunskapsgraf där varje nod har provenance och varje rand har självförtroende poäng

**Kom snart**: Hela LucidRAG-integrationen som visar hur dessa banor bildar sig i flera grafier.

---


## Slutsatsen

Architekturen har en struktur: varje våg är oberoende , varje signal är inskriven M SK2 varje upphöjning är deterministiska . Florenz MSC4 erbjuder snabb lokal analys Mska5 Vision LLM hanterar komplexa fall M Ska6 men inga av dem fungerar utan begränsningarMska7 deterministiska signaler angrippar alltid utgången

Sedan den första artikelpubliceringen, ,, har systemet utvecklats signifikant.

- **Florence-2 integration av ONNX** minskar API-kostnader och latens (~200ms lokal vs ~1-5s moln
- **Text- endast filmspår** att uppnå 30×-tokenreduktion för GIF-undertitel
- **Pipeline** väljer den optimala vägensättningen baserat på bilders egenskaper
- **Signalinsamlingar** att förenkla vanliga användarfall (@alttext, @motionM SK3
- **Desktop GUI** tillhandahåller drag-and-drop-analys med livesignalvisualisering

Bara den OCR-rörsverket, —, med sina tre nivåer: -, skalning av nivåerna: ,, multi: M SK3, skärmdumpning och optimering av filmvägar: Mska5, text: M Ska6, bara extraktion av fläcken: Mka7, har blivit tillräckligt komplicerad för att äga sin egen detaljerade artikel. [Vision OCR-integration](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/vision-ocr-integration.md) vägledning för den kompletta tekniska sammansättningen.

Om du kan göra detta för bilder— den mest stökiga inmatningstypen , med OCR-ljud , stiliserade fonter M SK3 animerade bilder Mska4 och hallucinationer M Ska5 antagliga titningar M ska6 kan du göra det för vilken sannolikhetskomponent som helst

Att ' är begränsad Fuzziness i praktiken

---


## resurser

### Repository

- **[LucidRAG-repository](https://github.com/scottgal/lucidrag)** - Hela källkod

### CLI-verktyg

- **[ImageSummarizer CLI](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.ImageSummarizer.Cli)** - Kommandot -linjerverktyg för bildanalys
- **[CLI README](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.ImageSummarizer.Cli/README.md)** - Installation
- **[Demobilder](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.ImageSummarizer.Cli/demo-images)** - Ett exempel på GIFs och ramsträngar som visas i denna artikel

### Kernbiblioteket

- **[DocSummarizer.Images](https://github.com/scottgal/lucidrag/tree/main/src/Mostlylucid.DocSummarizer.Images)** - Kernbildanalysbibliotek
- **[Biblioteksreader](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/README.md)** - API-dokumentationen , vågstrukturen
- **[Architecture Guide](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/architecture.md)** -
- **[Pipelinedokumentation](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/pipelines.md)** - automatiskt , balanserad , kvalitet M SK3 florens
- **[Vision OCR-integration](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/vision-ocr-integration.md)** -
- **[rörelseanalys](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/motion.md)** - Giframextraktion , rörelsedetektor
- **[Referens för signaler](https://github.com/scottgal/lucidrag/blob/main/src/Mostlylucid.DocSummarizer.Images/docs/signals.md)** - Signalkatalog

### Related Articles

- [DocSummarizer](/blog/building-a-document-summarizer-with-rag) - Dokumentet analyseras genom att använda liknande mönster
- [DataSummarizer](/blog/datasummarizer-how-it-works) - Dataprofilering med samma determinism

---


## Serien

| del | mönster ♫ ♫ | ♫ Axel ♫
| ---- | ------------------------------------------------------------------------- | ------------------------------- |
| 1    | [Begränsad otydighet](/blog/constrained-fuzziness-pattern) | Enkel komponent |
| 2    | [Begränsad Fuzzy MoM](/blog/constrained-mom-mixture-of-models) | Flera komponenter |
| 3    | [Kontext dragning](/blog/constrained-fuzzy-context-dragging) | tid / minne |
| 4    | **Image Intelligence (den här artikeln)**                                     | **Wave architecture, mönster** |
| 4.1  | [Det tre---Tier-OCR-röret](/blog/constrained-fuzzy-image-ocr-pipeline) | OCR

**Nästa**: Del 5 visar hur ImageSummarizer [DocSummarizer](/blog/building-a-document-summarizer-with-rag), och [DataSummarizer](/blog/datasummarizer-how-it-works) komponera till multi-modal graf RAG med LucidRAG.

Alla delar följer samma invariant **sannolikhetskomponenter föreslår ; deterministiska system förblir kvar**.