AI-Powered Alt Text Generation with mostlylucid.llmlltText
Vill du få trevliga, beskrivande alttext för bilder på dina webbplatser eller jsut extrahera text från dem? mostlylucid.llmalttext använder Microsoft's Florence
Nota: Jag behöver uppdatera den här dokumenten nu nuget package är ute. Om du tittar här du' kommer att få reda på en häftig demo-sida som du kan ladda ner och använda
Inleiding
Alttext spelar roll. Att skärmen-readerer är beroende av det , SEO-Rankingsfaktorerna påverkar det i, och det är helt enkelt det rätta att göra för tillgänglighet, . Men att skriva bra alttext för hundratals bilder,? Det är det som ' är där de flesta av oss misslyckas med.
Det här paketet löser problemet med hjälp av Microsoft's Florence
källkod: github.comM SK1scottgal/mostlylucid .nugetpackages
Problemet
Varje <img> tag skulle ha betydelsefull alt text. Men i praktiken:
- Handskrivande är tråkigt - hundratals bilder innebär timmars arbete
- AI APIs kostar pengar - OpenAI Vision
- Bekymmer om privatliv - du kanske inte vill skicka bilder till externa APIs
- Inkonsistent kvalitet - olika människor skriver alttext på olika sätt
Tänk om du kunde generera hög kvalitet alttext automatiskt på din egen hårdvara
Hur det fungerar
Paketet använder Microsofts modell, ', Florences modell och -2 via ONNX-runtimen.
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
Nyckelfunktionen:
- Lokalt utförande - inga API-sändningar , inga kostnader
- ~800MB modell - ladda ned en gång, kastars för alltid
- Flera typer av uppgifter - korta captionar , detaljerade beschreibunger, OCR
- Inhoudsklassificering - vet om det är ett foto
Vinnig Start
Installation
dotnet add package Mostlylucid.LlmAltText
Register Services
// Program.cs
builder.Services.AddAltTextGeneration();
Det är det. Den första versionen laddar ner Florences modell.
Generera Alt Text
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 });
}
}
Flera inmatningskällor
Servicen accepterar bilder från var som helst - filer , URLs M SK2 strömmar , eller bytskiffer
Från Lêerpfad
var altText = await _imageAnalysis.GenerateAltTextFromFileAsync("/images/photo.jpg");
Från URL
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(
"https://example.com/image.png");
Från ström
using var stream = file.OpenReadStream();
var altText = await _imageAnalysis.GenerateAltTextAsync(stream);
Från Byte Array
var bytes = await httpClient.GetByteArrayAsync(imageUrl);
var altText = await _imageAnalysis.GenerateAltTextAsync(bytes);
Tasktyper: Kontrollspecifika nivåer
Florence-2 supporterar tre caption-modi . Välj utifrån dina behov:
// 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."
När man ska använda var och en
| Uppgiftstyp | bäst för |
|---|---|
CAPTION |
Tappnalar , dekorativa bilder, snabb verktygstips |
DETAILED_CAPTION |
Sociala medier |
MORE_DETAILED_CAPTION |
Den fulla tillgänglighetenM SK1 skärmar läsare ( tillämpt |
OCR Textuttvingning
Florence-2 kan också extrahera text från bilder | - användbar för bildskärmdumpar |, | dokument | МSK3 | och diagram
// 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}");
innehållstyp klassificering
Alla bilder är inte likadana. Ett fotografi behöver deskriptiv alttext; ett dokument behöver dess textinnehåll
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}");
Att hantera olika typer av innehåll
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;
}
innehållstyp referens
| Typ | Beskrywing | exempel | ||||||
|---|---|---|---|---|---|---|---|---|
Photograph |
VerkligM SK1 världsbildar | Människor, landskap | ||||||
Document |
Text | |||||||
Screenshot |
Oprogramskapande ♫ | ♫ UI ♫ | ||||||
Chart |
Datavisualiseringar | Grafiska | , | tallriksdiagram | МSK3 | tabeller | ||
Illustration |
Tecknad innehåll | Konstverk, tecknade bilderM SK3 ikoner | ||||||
Diagram |
tekniska ritningar | Flowcharts | , | UML | ||||
Unknown |
Oklassificerad | Kanter vid kanten |
Det automatiska Alt Text-TagHelper
Här' är det som blir intressant. TagHelper genererar automatiskt alttext för alla <img> tag saknade ett - vid rendertid.
Konfiguration
// 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();
Registrera taghjältaren i _ViewImports.cshtml:
@addTagHelper *, Mostlylucid.LlmAltText
Hur det fungerar
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
Vad som processeras
<!-- 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" />
Domainbegränsningar
För säkerhet, kan du begränsa vilka domän som TagHelper kommer att få fram från:
options.AllowedImageDomains = new List<string>
{
"mycdn.example.com",
"images.mysite.org",
"cdn.githubusercontent.com"
};
Databas Caching
Utan kassering, skulle varje skriftskap återskapa alttexten. Det ' var långsamt och slösaktigtM SK3 Databasens kassrar sparar resultat som är krypterade av en bild-URL
SQLite (Development)
builder.Services.AddAltTextGeneration(options =>
{
options.EnableDatabase = true;
options.DbProvider = AltTextDbProvider.Sqlite;
options.SqliteDbPath = "./alttext.db";
options.CacheDurationMinutes = 60;
});
PostgreSQL (Production)
builder.Services.AddAltTextGeneration(options =>
{
options.EnableDatabase = true;
options.DbProvider = AltTextDbProvider.PostgreSql;
options.ConnectionString = Configuration.GetConnectionString("AltTextDb");
});
Konfigurationsreferens
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;
});
Verklig-World Example: Batch Processing
Här är hur jag använder den för att processa bilder när jag importerar bloggposter.
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";
}
}
Tillvägagångspunkter
Vad man förväntar sig
| Metrik | Typiskt värde | |||||
|---|---|---|---|---|---|---|
| Först ut | långsammare | ~800 | MB modelldownload | |||
| Modelllast | 1-3 | sekunder | МSK3 | |||
| PerM SK1bildbehandlande | 500-2000ms | |||||
| Membrans tillämpning | 2 | GB | {\displaystyle | } | ||
| Disk utrymme | ~800MB för modeller M |
Tipps för 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
}
OpenTelemetry integration
Paketet inkluderar byggt-inspårning:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddSource("Mostlylucid.LlmAltText");
});
spårade aktiviteter:
llmalttext.generate_alt_textllmalttext.extract_textllmalttext.analyze_imagellmalttext.classify_content_type
Hälsakontroller
Lägg till en hälsokontroll för att övervaka modellens status:
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");
Troubleshooting
Modelldownloading misslyckades
Error: Failed to download model files
Lösningar:
- kolla internetuppkoppling
- Verifiera firewall som tillåter Hugging Face -downloads
- Försäkra att ~800MB diskytan är tillgänglig
- Bevestig att skriva tillstånd på
ModelPath
Service är inte redo
_imageAnalysis.IsReady // Returns false
Lösningar:
- Vänta till modellinitialisering (1-3 sekunder
- Kontrollera protokoll för initialiseringsfehler
- Verifiera tillräckligt med minne (2GB+)
dålig kvalitet Alt Text
Lösningar:
- Använda
MORE_DETAILED_CAPTION(default) - Försäkra att inmatningsbilderna är tydliga
- Prüfa att bilden är "'", inte för liten eller suddig
TagHelper inte fungerar
Lösningar:
- Verifiera
EnableTagHelper = true - Kontroller
@addTagHelperi_ViewImports.cshtml - Använd absoluta URLs (relativa vägar är hoppade över
- Kontroller
AllowedImageDomainsKonfiguration
Möjligheter till tillgänglighet
Genererad alttext är en utgångspunkt
- Omvärdera utgången - AI är inte perfekt
- Håll det kort - 90-100 ord max
- Var deskriptiv - inkluderar subjekter , handlingar
- undvika överskott - donM SK1 inte börja med "Image of..."
- Tänk på meningen - alt text borde tjäna bilden 's roll på sidan
- Använd tom alt för dekorativa - uppsättning
alt=""för rent dekorativa bilder - Inbegripa synlig text - om bilden innehåller text
Slutsatsen
Mostlylucid.LlmAltText tar med sig AI- kraftfull tillgång till dina | .NET-applikationer utan kostnads- eller privatlivsproblem från externa APIs |. TagHelper gör det speciellt enkelt | <img> tag får automatic alt text.
Paketet är Licenslös (public domain), så gör vad du vill med det
resurser
- NuGet: Det mest tydliga.LlmAltText
- källa: github.comM SK1scottgal/mostlylucid .nugetpackages
- Emiten: GitHub-problem
- Florence-2: Microsofts visionspråksmodell