This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
KI---Powered Alt Text Generation mit meist schlüssigen ,.-llmlltText
Tuesday, 25 November 2025
Möchten Sie nett erhalten?,-deskriptive alt Text für Bilder auf Ihren Aufstellungsorten oder jsut extrahieren Text von ihnen.? mostlylucid.llmalttext verwendet Microsoft ,' , Florence , -2 , Vision Sprache Modell zu erzeugen hoch , - , Qualität alt Text automatisch , die vollständig lokal auf Ihrem Computer , , , keine API-Tasten erforderlich
Hinweis: Ich muss diese doc jetzt aktualisieren die Nuget-Paket Wenn du aussiehst Hierher Sie können Download-und Nutzungsmöglichkeiten für eine raffinierte Demo-Website, die Sie herunterladen und verwenden, um diese mit Details in den kommenden Tagen aktualisieren
Einleitung
Alt text matters-.-Bildschirmleser hängen davon ab -,-SEO-Rankings-Faktor es in -MSC2- und es ist einfach die richtige Sache, für Zugänglichkeit zu tun Aber schreiben gute alt Text für Hunderte von Bildern-MSC5-, Dass - '-, wo die meisten von uns fallen kurz
Dieses Paket löst, dass Problem mit Microsoft .' s Florence . -2 vision language model ?- ? läuft ganz lokal auf Ihrem Computer ? , ? keine API-Tasten erforderlich ?
Quelle: : github-.-com./-scottgal./-mostlylucid-.-nugetverpackungen
Das Problem
Jede <img> Tag sollte einen bedeutungsvollen alt Text haben... aber in der Praxis...
- Manuelles Schreiben ist mühsam Hunderte von Bildern bedeuten Arbeitsstunden
- KI-APIs kosten Geld OpenAI Vision, Claude-, usw., addieren Sie schnell
- Datenschutzbelange Vielleicht möchten Sie Bilder nicht an externe APIs senden.
- Uneinheitliche Qualität Andere Leute schreiben alt Text anders
Was, wenn du hoch erzeugen könntest?- quality alt Text automatisch?MSC1 laufe komplett auf deiner eigenen Hardware.
Wie es funktioniert
Das Paket verwendet Microsoft-Modell Florenz-Modell über ONNX-Laufzeit.. Hier ist die Verarbeitungspipeline:.
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
Wesentliche Merkmale
- Lokale Ausführung Keine API-Anrufe keine Kosten keine Datenschutzbedenken
- Modell ~800,MB Downloads einmalig gecached für immer
- Mehrere Aufgabentypen Kurze Beschreibungen - ausführliche Beschreibungen
- Inhaltsklassifizierung -, weiß wenn es ein Foto ist, ,, Diagramm, Screenshot usw. .,
Schnellstart
Installation
dotnet add package Mostlylucid.LlmAltText
Registerdienste
// Program.cs
builder.Services.AddAltTextGeneration();
Das ist es .. Der erste Lauf lädt das Florence-Modell -2.
Alt-Text generieren
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 });
}
}
Mehrere Eingangsquellen
Der Dienst akzeptiert Bilder von überall aus --Dateien, ,-URLs, ,-Streams oder Byte-Arrays
Aus dem Dateipfad
var altText = await _imageAnalysis.GenerateAltTextFromFileAsync("/images/photo.jpg");
Von der URL
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(
"https://example.com/image.png");
Aus Stream
using var stream = file.OpenReadStream();
var altText = await _imageAnalysis.GenerateAltTextAsync(stream);
Von Byte Array
var bytes = await httpClient.GetByteArrayAsync(imageUrl);
var altText = await _imageAnalysis.GenerateAltTextAsync(bytes);
Aufgabentypen .: . Kontrolle der Detailebene
Florence--2-Unterstützt drei Bildunterschriftsmodi - . Wählen Sie basierend auf Ihren Bedürfnissen -:-
// 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."
Wann Sie jedes Mal verwenden müssen
Aufgabentyp für die Aufgabenstellung am besten für die Bearbeitung
|-----------|----------|
| CAPTION |-Tumbnails,-dekorative Bilder,-schnelle Tooltips
| DETAILED_CAPTION Soziale Medien Grundlegende Zugänglichkeit
| MORE_DETAILED_CAPTION Weitere Informationen: http:www.cordis.lu/index.html
OCR-Textextraktion
Florence--2 , kann auch Text aus Bildern extrahieren, die für Screenshots nützlich sind., , Dokumente und Diagramme.
// 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}");
Einstufung nach Inhaltstyp
Nicht alle Bilder sind gleich..-Ein Foto braucht beschreibenden alt text, ein Dokument benötigt seinen Text Inhalt.
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}");
Umgang mit verschiedenen Inhaltstypen
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;
}
Angabe des Inhaltstyps
Beschreibung des Musters des Modells
|------|-------------|---------|
| Photograph Fotos von der realen - Welt Menschen Landschaften , Produkte |
| Document ,| , Text , - , schwerer Inhalt , | , PDFs , , , Formulare und Artikel
| Screenshot Software erfasst Websites von |, , und , Apps
| Chart Datenvisualisierungen Diagramme Diagramme Tabellen
| Illustration Zeichentrickfilme, Zeichentrick-Symbole und -Icons
| Diagram Technische Zeichnungen Technische Zeichnungen Flussdiagramme
| Unknown Nicht klassifizierte Kantenfälle
Der Auto Alt Text TagHelper
Hier, wo es interessant wird Der TagHelper erzeugt automatisch alt Text für jeden <img> Tag fehlt eins zum Renderzeitpunkt
Einrichtung
// 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();
Registrieren Sie den TagHelper in _ViewImports.cshtml:
@addTagHelper *, Mostlylucid.LlmAltText
Wie es funktioniert
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
Was verarbeitet wird
<!-- 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" />
Domänenbeschränkungen
Für die Sicherheit können Sie einschränken, welche Domains der TagHelper aus dem : holen wird
options.AllowedImageDomains = new List<string>
{
"mycdn.example.com",
"images.mysite.org",
"cdn.githubusercontent.com"
};
Datenbank-Caching
Ohne Caching... jede Seite Render würde alt Text regenerieren... das ist langsam und verschwenderisch.... die Datenbank speichert Ergebnisse, die von der Bild-URL geschlüsselt werden.
SQLite-Entwicklung – )
builder.Services.AddAltTextGeneration(options =>
{
options.EnableDatabase = true;
options.DbProvider = AltTextDbProvider.Sqlite;
options.SqliteDbPath = "./alttext.db";
options.CacheDurationMinutes = 60;
});
PostgreSQL Produktion
builder.Services.AddAltTextGeneration(options =>
{
options.EnableDatabase = true;
options.DbProvider = AltTextDbProvider.PostgreSql;
options.ConnectionString = Configuration.GetConnectionString("AltTextDb");
});
Einrichtungsreferenz
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;
});
Echtes Beispiel für die Batch-Verarbeitung von :
Hier ist, wie ich es benutze, um Bilder beim Importieren von Blogposts zu verarbeiten.
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";
}
}
Leistungsbeurteilungen
Was zu erwarten ist
Metrisches Messergebnis Typischer Wert |--------|--------------| Erster Lauf langsamerer Download von (~800MB Modelllast (msk) Bildbearbeitungs- und -bearbeitungsgeräte für die Bildverarbeitung Verwendung des Speichers von |, empfohlen für 2, Laufwerksspeicher ~800MB für Modelle |
Tipps für die Produktion
// 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 Integration
Das Paket beinhaltet eingebaute ,-'in Tracing- , :'
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddSource("Mostlylucid.LlmAltText");
});
Verfolgte Tätigkeiten
llmalttext.generate_alt_textllmalttext.extract_textllmalttext.analyze_imagellmalttext.classify_content_type
Gesundheitskontrollen
Fügen Sie einen Gesundheitscheck hinzu, um den Status des Modells zu überwachen.
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");
Fehlerbehebung
Modell-Download fehlgeschlagen
Error: Failed to download model files
Lösungen
- Internet-Verbindung überprüfen
- Firewall überprüfen ermöglicht Hugging Face Downloads
- Vergewissern Sie sich, dass der Festplattenspeicher von ~800.MB verfügbar ist
- Schreibrechte überprüfen auf
ModelPath
Dienst nicht bereit
_imageAnalysis.IsReady // Returns false
Lösungen
- Warten Sie auf Modellinitialisierung
- Protokolle auf Initialisierungsfehler überprüfen
- Überprüfe ausreichenden Speicher
Schlechte Qualität Alt Text
Lösungen
- Verwendung
MORE_DETAILED_CAPTION(-default-)- - Stellen Sie sicher, dass Eingabebilder klar sind
- Prüfen Bild ist nicht zu klein oder verschwommen
TagHelper funktioniert nicht
Lösungen
- Überprüfen
EnableTagHelper = true - Kontrolle
@addTagHelperin der_ViewImports.cshtml - Absolute URLs verwenden .( .relative Pfade werden übersprungen .
- Kontrolle
AllowedImageDomainsKonfiguration
Best Practices für Barrierefreiheit
Generierter Alttext ist ein Ausgangspunkt für beste Ergebnisse
- Überprüfung des Outputs Verifizieren Sie die Genauigkeit
- Halten Sie es kurz Maximale Anzahl der Wörter
- Deskriptiv sein Einschließlich Themen, Aktionen und Kontext
- Redundanz vermeiden Beginnen Sie mit dem Bild von ..."
- Überlegener Zweck Text sollte der Rolle des Bildes auf der Seite dienen.
- Verwenden Sie leere Alt für dekorative Satz
alt=""für rein dekorative Bilder - Sichtbarer Text einschließen Wenn das Bild Text enthält, ist es mit einzufügen.
Schlußfolgerung
Mostlylucid.LlmAltText bringt AIR- powered accessibility zu Ihren Anwendungen ohne die Kosten oder Datenschutz-Bedenken von externen APIs. Der TagHelper macht es besonders einfach. <img> Tags gewinnen automatisch alt text
Das Paket ist Unlicense, öffentliche Domäne, also tun Sie, was immer Sie wollen.
Aufkommen
- NuGet-:- Meistlylucid, ., LmAltText
- Quelle: Eurostat. github-.-com./-scottgal./-mostlylucid-.-nugetverpackungen
- Probleme GitHub-Probleme
- Florenz ,-2: Microsoft®'s Vision-Sprachenmodell