# AI-Powered Alt Text Generation met veelal lucid.llmlltText

Wilt u mooie, beschrijvende alt tekst voor afbeeldingen op uw sites of jsut extraheren tekst van hen? `mostlylucid.llmalttext` maakt gebruik van Microsoft's Florence-2 visie taal model om hoge kwaliteit alt tekst automatisch te genereren - volledig lokaal draait op uw machine, geen API sleutels nodig.

> Opmerking: Ik moet deze doc updaten nu de [nuget-pakket ](https://www.nuget.org/packages/Mostlylucid.LlmAltText)Als je kijkt... [Hier.](https://github.com/scottgal/mostlylucid.nugetpackages/tree/main/Mostlylucid.AltText.Demo) je zult fijn een handige demo site die u kunt downloaden en gebruiken. Ik zal dit bijwerken met details in de komende dagen.

<datetime class="hidden">2025-11-24T10:00</datetime>

<!-- category -- ASP.NET, Accessibility, AI, NuGet, Florence-2, Image Processing -->
[![NuGet](https://img.shields.io/nuget/v/mostlylucid.llmaltText.svg)](https://www.nuget.org/packages/mostlylucid.llmalttext) [![Licentie: Unlicense](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)

# Inleiding

Alt tekst is belangrijk. Screen lezers hangen ervan af, SEO rankings factor het in, en het is gewoon het juiste ding om te doen voor toegankelijkheid. Maar het schrijven van goede alt tekst voor honderden afbeeldingen? Dat is waar de meesten van ons tekort komen.

Dit pakket lost dat probleem op met behulp van Microsoft's Florence-2 visie taalmodel - volledig lokaal draait op uw machine, geen API sleutels nodig.

**Broncode:** [github.com/scottgal/meestallucid.nugetpackages](https://github.com/scottgal/mostlylucid.nugetpackages/tree/main/Mostlylucid.LlmAltText)

[TOC]

# Het probleem

Elke `<img>` tag zou betekenisvolle alt tekst moeten hebben. Maar in de praktijk:

- **Handmatig schrijven is vervelend.** - honderden beelden betekent uren werk
- **AI API's kosten geld** - OpenAI Vision, Claude, etc. snel optellen
- **Privacyproblemen** - u wilt geen afbeeldingen naar externe API's sturen
- **Inconsistente kwaliteit** - verschillende mensen schrijven alt tekst anders

Wat als je alt-tekst van hoge kwaliteit automatisch kunt genereren, volledig draait op je eigen hardware?

# Hoe het werkt

Het pakket maakt gebruik van Microsoft's Florence-2 model via ONNX runtime. Hier is de verwerkingspijplijn:

```mermaid
flowchart TB
    subgraph Input[Image Sources]
        A[File Path]
        B[URL]
        C[Stream]
        D[Byte Array]
    end

    subgraph Processing[Florence-2 Pipeline]
        E[Image Preprocessing]
        F[Vision Encoder]
        G[Language Decoder]
    end

    subgraph Output[Results]
        H[Alt Text]
        I[OCR Text]
        J[Content Type]
    end

    A --> E
    B --> E
    C --> E
    D --> E
    E --> F
    F --> G
    G --> H
    G --> I
    G --> J

    style A stroke:#10b981,stroke-width:2px
    style B stroke:#10b981,stroke-width:2px
    style C stroke:#10b981,stroke-width:2px
    style D stroke:#10b981,stroke-width:2px
    style F stroke:#6366f1,stroke-width:2px
    style G stroke:#6366f1,stroke-width:2px
    style H stroke:#ec4899,stroke-width:2px
    style I stroke:#ec4899,stroke-width:2px
    style J stroke:#ec4899,stroke-width:2px
```

**Belangrijkste kenmerken:**

- **Lokale uitvoering** - geen API-gesprekken, geen kosten, geen privacyproblemen
- **~800MB model** - één keer downloaden, voor altijd gecached
- **Meerdere takentypes** - korte bijschriften, gedetailleerde beschrijvingen, OCR
- **Inhoudsclassificatie** - weet of het een foto, grafiek, screenshot, enz. is.

# Snel starten

## Installatie

```bash
dotnet add package Mostlylucid.LlmAltText
```

## Diensten registreren

```csharp
// Program.cs
builder.Services.AddAltTextGeneration();
```

De eerste run downloadt het Florence-2 model (~800MB), dan ben je klaar om te gaan.

## Alttekst aanmaken

```csharp
public class ImageController : ControllerBase
{
    private readonly IImageAnalysisService _imageAnalysis;

    public ImageController(IImageAnalysisService imageAnalysis)
    {
        _imageAnalysis = imageAnalysis;
    }

    [HttpPost("analyze")]
    public async Task<IActionResult> Analyze(IFormFile image)
    {
        using var stream = image.OpenReadStream();
        var altText = await _imageAnalysis.GenerateAltTextAsync(stream);

        return Ok(new { altText });
    }
}
```

# Meerdere invoerbronnen

De dienst accepteert afbeeldingen van overal - bestanden, URL's, streams, of byte arrays.

## Van bestandspad

```csharp
var altText = await _imageAnalysis.GenerateAltTextFromFileAsync("/images/photo.jpg");
```

## Van URL

```csharp
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(
    "https://example.com/image.png");
```

## Van stroom

```csharp
using var stream = file.OpenReadStream();
var altText = await _imageAnalysis.GenerateAltTextAsync(stream);
```

## Van Byte Array

```csharp
var bytes = await httpClient.GetByteArrayAsync(imageUrl);
var altText = await _imageAnalysis.GenerateAltTextAsync(bytes);
```

# Taaktypes: Detailniveau controleren

Florence-2 ondersteunt drie bijschriften. Kies op basis van uw behoeften:

```csharp
// Brief - "A dog sitting on grass"
var brief = await _imageAnalysis.GenerateAltTextAsync(stream, "CAPTION");

// Detailed - "A golden retriever sitting on green grass in a park"
stream.Position = 0;
var detailed = await _imageAnalysis.GenerateAltTextAsync(stream, "DETAILED_CAPTION");

// Most detailed (default) - Full accessibility description
stream.Position = 0;
var full = await _imageAnalysis.GenerateAltTextAsync(stream, "MORE_DETAILED_CAPTION");
// "A happy golden retriever with light fur sitting on lush green grass
//  in a sunny park, with trees visible in the background."
```

**Wanneer te gebruiken:**

Taaktype Best Voor
|-----------|----------|
| `CAPTION` Miniaturen, decoratieve afbeeldingen, snelle tooltips
| `DETAILED_CAPTION` Sociale media, basistoegankelijkheid
| `MORE_DETAILED_CAPTION` Volledige toegankelijkheid, schermlezers (aanbevolen)

# OCR-tekstextractie

Florence-2 kan ook tekst uit afbeeldingen halen - nuttig voor screenshots, documenten en grafieken.

```csharp
// Extract text only
var extractedText = await _imageAnalysis.ExtractTextAsync(stream);

// Get both alt text and extracted text
var (altText, ocrText) = await _imageAnalysis.AnalyzeImageAsync(stream);

Console.WriteLine($"Alt: {altText}");
Console.WriteLine($"OCR: {ocrText}");
```

# Inhoudstype-classificatie

Niet alle afbeeldingen zijn hetzelfde. Een foto heeft een beschrijvende alt tekst nodig; een document heeft de tekstinhoud nodig. De classificatiefunctie helpt u elk goed te behandelen:

```csharp
var result = await _imageAnalysis.AnalyzeWithClassificationAsync(stream);

Console.WriteLine($"Type: {result.ContentType}");        // e.g., "Photograph"
Console.WriteLine($"Confidence: {result.ContentTypeConfidence:P0}"); // e.g., "87%"
Console.WriteLine($"Has Text: {result.HasSignificantText}");
```

## Omgaan met verschillende inhoudstypen

```csharp
var result = await _imageAnalysis.AnalyzeWithClassificationAsync(stream);

switch (result.ContentType)
{
    case ImageContentType.Document:
        // Documents - prioritize extracted text
        return result.ExtractedText;

    case ImageContentType.Screenshot:
        // Screenshots - combine description with UI text
        return result.HasSignificantText
            ? $"{result.AltText}. Text visible: {result.ExtractedText}"
            : result.AltText;

    case ImageContentType.Chart:
        // Charts - describe the visualization plus data
        return $"{result.AltText}. Data: {result.ExtractedText}";

    case ImageContentType.Photograph:
    default:
        // Photos - just the description
        return result.AltText;
}
```

## Referentie van het type inhoud

Beschrijving van het type: Voorbeeld:
|------|-------------|---------|
| `Photograph` Real-world foto's Mensen, landschappen, producten
| `Document` Text-heavy content PDF's, formulieren, artikelen
| `Screenshot` De software vangt de UI, websites, apps
| `Chart` Data visualisaties Graphs, taart grafieken, tabellen
| `Illustration` Kunstwerk, tekenfilms, pictogrammen
| `Diagram` Technische tekeningen Flowcharts, UML, schema's
| `Unknown` Niet-ingedeelde Edge cases

# De Auto Alt Tekst TagHelper

Hier is waar het interessant wordt. De TagHelper genereert automatisch alt tekst voor elke `<img>` tag ontbreekt een - op render tijd.

## Instellen

```csharp
// Program.cs
builder.Services.AddAltTextGeneration(options =>
{
    options.EnableTagHelper = true;
    options.EnableDatabase = true;  // Cache results
    options.DbProvider = AltTextDbProvider.Sqlite;
    options.SqliteDbPath = "./alttext.db";
});

var app = builder.Build();
await app.Services.MigrateAltTextDatabaseAsync();
```

Registreer de TagHelper in `_ViewImports.cshtml`:

```cshtml
@addTagHelper *, Mostlylucid.LlmAltText
```

## Hoe het werkt

```mermaid
flowchart LR
    subgraph Razor[Razor View Rendering]
        A[img tag found]
        B{Has alt attribute?}
        C[Skip - use existing]
        D{In cache?}
        E[Return cached]
        F[Fetch image]
        G[Generate alt text]
        H[Cache result]
        I[Render with alt]
    end

    A --> B
    B -->|Yes| C
    B -->|No| D
    D -->|Yes| E
    D -->|No| F
    F --> G
    G --> H
    H --> I
    E --> I

    style A stroke:#10b981,stroke-width:2px
    style B stroke:#6366f1,stroke-width:2px
    style G stroke:#ec4899,stroke-width:2px
    style I stroke:#8b5cf6,stroke-width:2px
```

## Wat verwerkt wordt

```html
<!-- NO ALT - Will be processed -->
<img src="https://example.com/photo.jpg" />

<!-- HAS ALT - Skipped (respects your text) -->
<img src="https://example.com/photo.jpg" alt="My custom description" />

<!-- EMPTY ALT - Skipped (decorative image per a11y standards) -->
<img src="https://example.com/decorative.jpg" alt="" />

<!-- EXPLICIT SKIP - Skipped -->
<img src="https://example.com/photo.jpg" data-skip-alt="true" />

<!-- DATA URI - Skipped (can't fetch) -->
<img src="data:image/png;base64,..." />

<!-- RELATIVE PATH - Skipped (needs absolute URL) -->
<img src="/images/photo.jpg" />
```

## Domeinbeperkingen

Voor de beveiliging, kunt u beperken welke domeinen de TagHelper zal halen uit:

```csharp
options.AllowedImageDomains = new List<string>
{
    "mycdn.example.com",
    "images.mysite.org",
    "cdn.githubusercontent.com"
};
```

# Database caching

Zonder caching zou elke pagina render alt tekst regenereren. Dat is traag en verspillend. De database cache slaat resultaten op die door image URL worden getoetst.

## SQLite (Ontwikkeling)

```csharp
builder.Services.AddAltTextGeneration(options =>
{
    options.EnableDatabase = true;
    options.DbProvider = AltTextDbProvider.Sqlite;
    options.SqliteDbPath = "./alttext.db";
    options.CacheDurationMinutes = 60;
});
```

## PostgreSQL (productie)

```csharp
builder.Services.AddAltTextGeneration(options =>
{
    options.EnableDatabase = true;
    options.DbProvider = AltTextDbProvider.PostgreSql;
    options.ConnectionString = Configuration.GetConnectionString("AltTextDb");
});
```

# Configuratiereferentie

```csharp
builder.Services.AddAltTextGeneration(options =>
{
    // Model location (~800MB downloaded here)
    options.ModelPath = "./models";

    // Default task type for alt text generation
    options.DefaultTaskType = "MORE_DETAILED_CAPTION";

    // Maximum word count for alt text
    options.MaxWords = 90;

    // Enable detailed logging
    options.EnableDiagnosticLogging = true;

    // TagHelper settings
    options.EnableTagHelper = true;
    options.EnableDatabase = true;
    options.AutoMigrateDatabase = true;

    // Database provider
    options.DbProvider = AltTextDbProvider.Sqlite;
    options.SqliteDbPath = "alttext.db";
    // or
    options.DbProvider = AltTextDbProvider.PostgreSql;
    options.ConnectionString = "Host=localhost;Database=alttext;...";

    // Security
    options.AllowedImageDomains = new List<string> { "cdn.example.com" };
    options.SkipSrcPrefixes = new List<string> { "data:", "blob:" };

    // Caching
    options.CacheDurationMinutes = 60;
});
```

# Real-World Voorbeeld: Batch Processing

Hier is hoe ik het gebruik om afbeeldingen te verwerken bij het importeren van blogberichten:

```csharp
public class ImageProcessor
{
    private readonly IImageAnalysisService _imageAnalysis;
    private readonly ILogger<ImageProcessor> _logger;

    public ImageProcessor(
        IImageAnalysisService imageAnalysis,
        ILogger<ImageProcessor> logger)
    {
        _imageAnalysis = imageAnalysis;
        _logger = logger;
    }

    public async Task ProcessMarkdownImagesAsync(string markdownPath)
    {
        var imageDir = Path.Combine(Path.GetDirectoryName(markdownPath)!, "images");
        if (!Directory.Exists(imageDir)) return;

        var images = Directory.GetFiles(imageDir, "*.*")
            .Where(f => IsImageFile(f));

        foreach (var imagePath in images)
        {
            try
            {
                var result = await _imageAnalysis
                    .AnalyzeWithClassificationFromFileAsync(imagePath);

                _logger.LogInformation(
                    "Processed {File}: {Type} ({Confidence:P0})",
                    Path.GetFileName(imagePath),
                    result.ContentType,
                    result.ContentTypeConfidence);

                // Store alt text for later use
                await SaveAltTextAsync(imagePath, result.AltText);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to process {File}", imagePath);
            }
        }
    }

    private static bool IsImageFile(string path)
    {
        var ext = Path.GetExtension(path).ToLowerInvariant();
        return ext is ".jpg" or ".jpeg" or ".png" or ".gif" or ".webp" or ".bmp";
    }
}
```

# Prestatieoverwegingen

## Wat te verwachten

Typische waarde
|--------|--------------|
Laag (~800MB model downloaden) Laag (~800MB model downloaden)
Modelbelasting in seconden
Per beeldverwerking 500-2000ms
Geheugengebruik 2GB+ aanbevolen
Schijfruimte 800MB voor modellen

## Tips voor de productie

```csharp
// 1. Register as Singleton (model load is expensive)
builder.Services.AddAltTextGeneration(); // Already singleton internally

// 2. Check readiness before processing
if (!_imageAnalysis.IsReady)
{
    return StatusCode(503, "AI model still initializing");
}

// 3. Use cancellation tokens for timeouts
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(url, cts.Token);

// 4. Process in batches, not parallel (memory constraints)
foreach (var image in images)
{
    await ProcessImageAsync(image); // Sequential is safer
}
```

# OpenTelemetrie-integratie

Het pakket omvat ingebouwde opsporing:

```csharp
builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.AddSource("Mostlylucid.LlmAltText");
    });
```

**Getraceerde activiteiten:**

- `llmalttext.generate_alt_text`
- `llmalttext.extract_text`
- `llmalttext.analyze_image`
- `llmalttext.classify_content_type`

# Gezondheidscontroles

Voeg een gezondheidscontrole toe om de status van het model te controleren:

```csharp
public class AltTextHealthCheck : IHealthCheck
{
    private readonly IImageAnalysisService _service;

    public AltTextHealthCheck(IImageAnalysisService service)
        => _service = service;

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        return Task.FromResult(_service.IsReady
            ? HealthCheckResult.Healthy("Florence-2 model ready")
            : HealthCheckResult.Unhealthy("Model not initialized"));
    }
}

// Registration
builder.Services.AddHealthChecks()
    .AddCheck<AltTextHealthCheck>("alttext");
```

# Problemen oplossen

## Downloaden van modellen is mislukt

```
Error: Failed to download model files
```

**Oplossingen:**

- Controleer internetconnectiviteit
- Firewall verifiëren maakt het mogelijk om Hugging Face-downloads te downloaden
- Zorg ervoor dat ~800MB schijfruimte beschikbaar is
- Schrijfrechten controleren op `ModelPath`

## Service is nog niet klaar

```csharp
_imageAnalysis.IsReady // Returns false
```

**Oplossingen:**

- Wacht op modelinitialisatie (1-3 seconden)
- Logboeken controleren op initialisatiefouten
- Controleer voldoende geheugen (2GB+)

## Alt-tekst van slechte kwaliteit

**Oplossingen:**

- Gebruik `MORE_DETAILED_CAPTION` (standaard)
- Zorg ervoor dat de invoerafbeeldingen duidelijk zijn
- Afbeelding controleren is niet te klein of wazig

## TagHelper werkt niet

**Oplossingen:**

- Verifiëren `EnableTagHelper = true`
- Controleren `@addTagHelper` in `_ViewImports.cshtml`
- absolute URL's gebruiken (relatieve paden worden overgeslagen)
- Controleren `AllowedImageDomains` configuratie

# Toegankelijkheid Beste praktijken

Gegenereerde alt tekst is een startpunt. Voor de beste resultaten:

1. **Evaluatie van de uitvoer** AI is niet perfect, controleer de nauwkeurigheid.
2. **Hou het kort.** - maximaal 90-100 woorden
3. **Descriptief zijn** - omvatten onderwerpen, acties, context
4. **Vermijd redundantie** - begin niet met "Afbeelding van..."
5. **Beschouw het doel** - alt tekst dient de rol van de afbeelding op de pagina
6. **Gebruik lege alt voor decoratief** - ingesteld `alt=""` voor puur decoratieve afbeeldingen
7. **Zichtbare tekst invoegen** - als afbeelding tekst bevat, invoegen

# Conclusie

`Mostlylucid.LlmAltText` brengt AI-aangedreven toegankelijkheid naar uw .NET toepassingen zonder de kosten of privacy zorgen van externe API's. De TagHelper maakt het bijzonder gemakkelijk - gewoon inschakelen en uw `<img>` tags krijgen automatisch alt tekst.

Het pakket is Unlicense (publiek domein), dus doe ermee wat je wilt.

## Middelen

- **NuGet:** [Meestal lucid.LlmAltText](https://www.nuget.org/packages/Mostlylucid.LlmAltText)
- **Bron:** [github.com/scottgal/meestallucid.nugetpackages](https://github.com/scottgal/mostlylucid.nugetpackages/tree/main/Mostlylucid.LlmAltText)
- **Onderwerpen:** [GitHub-problemen](https://github.com/scottgal/mostlylucidweb/issues)
- **Florence-2:** [Microsoft's Vision Language Model](https://huggingface.co/microsoft/Florence-2-base)