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 Als je kijkt... Hier. je zult fijn een handige demo site die u kunt downloaden en gebruiken. Ik zal dit bijwerken met details in de komende dagen.
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
Elke <img> tag zou betekenisvolle alt tekst moeten hebben. Maar in de praktijk:
Wat als je alt-tekst van hoge kwaliteit automatisch kunt genereren, volledig draait op je eigen hardware?
Het pakket maakt gebruik van Microsoft's Florence-2 model via ONNX runtime. Hier is de verwerkingspijplijn:
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:
dotnet add package Mostlylucid.LlmAltText
// Program.cs
builder.Services.AddAltTextGeneration();
De eerste run downloadt het Florence-2 model (~800MB), dan ben je klaar om te gaan.
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 });
}
}
De dienst accepteert afbeeldingen van overal - bestanden, URL's, streams, of byte arrays.
var altText = await _imageAnalysis.GenerateAltTextFromFileAsync("/images/photo.jpg");
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(
"https://example.com/image.png");
using var stream = file.OpenReadStream();
var altText = await _imageAnalysis.GenerateAltTextAsync(stream);
var bytes = await httpClient.GetByteArrayAsync(imageUrl);
var altText = await _imageAnalysis.GenerateAltTextAsync(bytes);
Florence-2 ondersteunt drie bijschriften. Kies op basis van uw behoeften:
// 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)
Florence-2 kan ook tekst uit afbeeldingen halen - nuttig voor screenshots, documenten en grafieken.
// 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}");
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:
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}");
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;
}
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
Hier is waar het interessant wordt. De TagHelper genereert automatisch alt tekst voor elke <img> tag ontbreekt een - op render tijd.
// 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:
@addTagHelper *, Mostlylucid.LlmAltText
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
<!-- 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" />
Voor de beveiliging, kunt u beperken welke domeinen de TagHelper zal halen uit:
options.AllowedImageDomains = new List<string>
{
"mycdn.example.com",
"images.mysite.org",
"cdn.githubusercontent.com"
};
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.
builder.Services.AddAltTextGeneration(options =>
{
options.EnableDatabase = true;
options.DbProvider = AltTextDbProvider.Sqlite;
options.SqliteDbPath = "./alttext.db";
options.CacheDurationMinutes = 60;
});
builder.Services.AddAltTextGeneration(options =>
{
options.EnableDatabase = true;
options.DbProvider = AltTextDbProvider.PostgreSql;
options.ConnectionString = Configuration.GetConnectionString("AltTextDb");
});
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;
});
Hier is hoe ik het gebruik om afbeeldingen te verwerken bij het importeren van blogberichten:
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";
}
}
Typische waarde |--------|--------------| Laag (~800MB model downloaden) Laag (~800MB model downloaden) Modelbelasting in seconden Per beeldverwerking 500-2000ms Geheugengebruik 2GB+ aanbevolen Schijfruimte 800MB voor modellen
// 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
}
Het pakket omvat ingebouwde opsporing:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddSource("Mostlylucid.LlmAltText");
});
Getraceerde activiteiten:
llmalttext.generate_alt_textllmalttext.extract_textllmalttext.analyze_imagellmalttext.classify_content_typeVoeg een gezondheidscontrole toe om de status van het model te controleren:
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");
Error: Failed to download model files
Oplossingen:
ModelPath_imageAnalysis.IsReady // Returns false
Oplossingen:
Oplossingen:
MORE_DETAILED_CAPTION (standaard)Oplossingen:
EnableTagHelper = true@addTagHelper in _ViewImports.cshtmlAllowedImageDomains configuratieGegenereerde alt tekst is een startpunt. Voor de beste resultaten:
alt="" voor puur decoratieve afbeeldingenMostlylucid.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.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.