# Mostlylucid.OcrNer - Le paquet NuGet (Part 2)

<!-- category -- AI,OCR,NER,ONNX,CSharp,Tutorial,NuGet -->
<datetime class="hidden">2026-02-12T12:00</datetime>

[![NuGet](https://img.shields.io/nuget/v/Mostlylucid.OcrNer)](https://www.nuget.org/packages/Mostlylucid.OcrNer/) [![NuGet téléchargements](https://img.shields.io/nuget/dt/Mostlylucid.OcrNer)](https://www.nuget.org/packages/Mostlylucid.OcrNer/) [![Publication de GitHub (CLI)](https://img.shields.io/github/v/release/scottgal/mostlylucidweb?filter=ocrner-*&label=CLI)](https://github.com/scottgal/mostlylucidweb/releases?q=ocrner)

À l'intérieur [Partie 1](/blog/simple-ocr-ner-extraction) J’ai montré le pipeline brut: télécharger manuellement les modèles , écrire un tokenizerM SK2 brancher l’inférence ONNX, et décoder les balises BIO à la mainMSC4 ÉducationMNK5 mais beaucoup de plomberie pour se faire bienMRK6

Maintenant, ' est un paquet NuGet. **Une ligne de configuration, téléchargement du modèle zéro** - tout automatiqueM SK1downloads à première utilisation.

> **Note:** Ce paquet est un outil simplifié pour extraire du texte et des entités d'images. *Toute chose* (photosM SK1 documents, screenshots , manuscriptifMSC4 gifs animés et même vidéosMST5 avec matchage fuzzyMSP6 consensus OCRMSV7 extraction structuréeMSS8 voir [***lucide*RAG**](https://www.lucidrag.com) où se trouve la version de niveau de production de ce pipeline-

[TOC]

---


## Glossaire rapide (Si vous êtes nouveau(e) à cet article'

Avant de nous plonger dans le langage, voici ce que signifient les termes clés :

- **OCR** (Reconnaissance des caractères optiquesM SK1 - Convertir une image de texte en caractères textuels réels votre code peut fonctionner avec
- **NER** (Reconnaissance des entités désignées) -analyse du texte pour trouver et classer les noms d'objetsM SK3 |"John Smith travaille chez Microsoft à SeattleMSC5 devient=: John Smith MSC7 PersonneMSM8 Microsoft SMC9 OrganisationMST10 Seattle R= Lieu de travailMSL12
- **Le temps de fonctionnement d'ONNX** - une façon de faire fonctionner les modèles d'apprentissage de la machine  comme le modèle BERT que nous utilisons pour l'NERM SK2 sur votre machine sans avoir besoin de Python, TensorFlowMSC4 ou un GPUMNK5 Il fonctionne comme un portatif `.onnx` fichier, localement, en utilisant uniquement votre CPU .
- **BERT** - un modèle de langage préalable à - formé par Google qui comprend le contexte dans le texte [CoNLL-2003](https://www.clips.uantwerpen.be/conll2003/ner/) ensemble de données pour reconnaître les personnes, organismesM SK1 emplacements , et diverses entités.
- **Florence-2** - un petit modèle de vision de Microsoft qui peut décrire ce qu’il *Voir* dans l'image (captionsM SK1objets , texte). Différencié de Tesseract en ce qu'il comprend la scène entière

---


## Pourquoi plus que simple Tesseract?

Tesseract est puissant pour le texte de documents nettoyés, mais il tombe sur les photos bruyantesM SK1 faibles - scans de contraste, et mixte MST4 scène MST5 texteM ST6 imagesM st7 Il s'arrête également au texte brutMst8 vous avez encore besoin d'un code supplémentaire pour transformer ce texte en entités structurées que vous pouvez effectivement utiliserMSST9

Ce paquet comble ces lacunes:

1. **[Graphique de l'image](https://sixlabors.com/products/imagesharp/) prétraitement** - échelle griseM SK1 accroissement du contraste , aperçu en fonction de l'OCR
2. **[OpenCV](https://opencv.org/) prétraitement avancé** - deskewM SK1 denoise, et binarisation pour les documents endommagés /skewed.
3. **[Florence-2](https://huggingface.co/microsoft/Florence-2-base)** vision - captions d'image locale et OCR via ONNX (sans API nuageux)
4. **BERT NER en haut du texte OCR** - convertir le texte extrait en entités typées (PERM SK2ORG/LOCMSC4MISC+) vous pouvez agir sur
5. **[Microsoft.Recognizers.Texte](https://github.com/microsoft/Recognizers-Text)** Règle --extraction des dates fondée sur les numéros ,Numéros ,Urls ,Téléphones
6. **Intégration appropriée de l'ID** - `AddOcrNer()` et vous avez terminé
7. **Outil CLI** - A [Spectre.Console](https://spectreconsole.net/) command- app de ligne qui fonctionne tout simplement hors de la boîte

---


## Ce qui a changé à partir de la partie 1

```mermaid
flowchart LR
    subgraph Part1["Part 1: Manual"]
        M1[Download models]
        M2[Write tokenizer]
        M3[Wire ONNX]
        M4[BIO decode]
    end

    subgraph Part2["Part 2: NuGet Package"]
        N1["AddOcrNer()"]
        N2[Auto-download]
        N3[ImageSharp + OpenCV]
        N4[Florence-2]
        N5[Recognizers]
        N6[CLI Tool]
    end

    Part1 -->|"packaged into"| Part2

    style N1 stroke:#090,stroke-width:3px
    style N2 stroke:#090,stroke-width:3px
    style N3 stroke:#f60,stroke-width:3px
    style N4 stroke:#f60,stroke-width:3px
    style N5 stroke:#f60,stroke-width:3px
    style N6 stroke:#f60,stroke-width:3px
```

La partie 1 était éducative - comprenait ce que chaque pièce fait

---


## Démarrage

### Installer

```bash
dotnet add package Mostlylucid.OcrNer
```

### Services de registre

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `AddOcrNer()` la méthode d'extension enregistre tout: OCR , NERM SK2 le pipeline combiné, FlorenceMST4 visionMSC5 le téléchargeur de modèlesMSP6 et le préprocesseur d'imagesMSV7 Tous comme singletonsMSS8 tous lazyM SS9initialisésSSS10

Voici le code d’enregistrement réel de ' `ServiceCollectionExtensions.cs`:

```csharp
// Option 1: From appsettings.json (reads the "OcrNer" section)
builder.Services.AddOcrNer(builder.Configuration);

// Option 2: Inline configuration
builder.Services.AddOcrNer(config =>
{
    config.EnableOcr = true;
    config.TesseractLanguage = "eng";
    config.MinConfidence = 0.5f;
});
```

Il n’y a pas de téléchargement du modèle, aucun cheminement des fichiers, aucun câblage ONNX. `AddOcrNer()` enregistre ces services:

```csharp
// From ServiceCollectionExtensions.cs - what gets registered
services.AddSingleton<ModelDownloader>();           // Auto-downloads models on first use
services.AddSingleton<ImagePreprocessor>();         // ImageSharp-based image enhancement
services.AddSingleton<OpenCvPreprocessor>();        // OpenCV advanced preprocessing
services.AddSingleton<INerService, NerService>();   // BERT NER from text
services.AddSingleton<IOcrService, OcrService>();   // Tesseract OCR from images
services.AddSingleton<IOcrNerPipeline, OcrNerPipeline>();         // Combined OCR + NER
services.AddSingleton<ITextRecognizerService, TextRecognizerService>(); // Microsoft.Recognizers
services.AddSingleton<IVisionService, VisionService>();           // Florence-2 vision
```

### Configuration (appsettings.jsonM SK2

```json
{
  "OcrNer": {
    "EnableOcr": true,
    "TesseractLanguage": "eng",
    "MinConfidence": 0.5,
    "MaxSequenceLength": 512,
    "ModelDirectory": "models/ocrner",
    "Preprocessing": "Default",
    "EnableAdvancedPreprocessing": false,
    "EnableRecognizers": false,
    "RecognizerCulture": "en-us"
  }
}
```

Voici ce qui est le cas : `OcrNerConfig` classez ces cartes à:

```csharp
// From OcrNerConfig.cs
public class OcrNerConfig
{
    public string ModelDirectory { get; set; } =
        Path.Combine(AppContext.BaseDirectory, "models", "ocrner");
    public bool EnableOcr { get; set; } = true;
    public string TesseractLanguage { get; set; } = "eng";
    public int MaxSequenceLength { get; set; } = 512;
    public float MinConfidence { get; set; } = 0.5f;
    public string NerModelRepo { get; set; } = "protectai/bert-base-NER-onnx";
    public PreprocessingLevel Preprocessing { get; set; } = PreprocessingLevel.Default;
    public bool EnableAdvancedPreprocessing { get; set; } = false;  // OpenCV pipeline
    public bool EnableRecognizers { get; set; } = false;            // Microsoft.Recognizers
    public string RecognizerCulture { get; set; } = "en-us";       // Recognizer language
}
```

Tous les paramètres ont des valeurs par défaut sensibles. Vous pouvez omettre l'ensemble de la section et tout fonctionne.`EnableAdvancedPreprocessing` et `EnableRecognizers`) par défaut à `false` de sorte que le paquet demeure léger pour les utilisateurs qui n’en ont pas besoin.

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `Preprocessing` option contrôle l'amélioration de l'image avant OCR:

| Valeur | Ce qu'il fait MSC2 Quand utiliser SMC3
|-------|-------------|-------------|
| `None` | Pas de prétraitement | Les images sont déjà optimisées |
| `Minimal` | Seulement à l'échelle grise
| `Default` | Taille grise + contraste ≥+ apercevoir MSC3 La plupart des images SMC4 recommandéesS MC5 SMC6
| `Aggressive` | Un contraste fort + Apercevoir MSC2 à grande échelle MSC3 Photos de mauvaise qualité SMC4

---


## Les quatre services

Le paquet enregistre cinq services, chacun utilisable indépendamment. Choisissez l'un qui convient à votre cas d'utilisation - làMSC3 il n'est pas nécessaire de charger FlorenceM SK4 si tout ce dont vous avez besoin est NER du texteMST5

```mermaid
flowchart TD
    subgraph Services
        NER["INerService<br>Text → Entities"]
        OCR["IOcrService<br>Image → Text"]
        REC["ITextRecognizerService<br>Text → Signals"]
        PIPE["IOcrNerPipeline<br>Image → Entities + Signals"]
        VIS["IVisionService<br>Image → Caption"]
    end

    OCR --> PIPE
    NER --> PIPE
    REC -.-> PIPE

    style PIPE stroke:#090,stroke-width:3px
    style VIS stroke:#f60,stroke-width:3px
    style REC stroke:#f60,stroke-width:2px,stroke-dasharray: 5 5
```

### Choix du bon service pour votre cas d'utilisation

Le principal principe est **Efficacité**: choisissez l’outil le plus léger qui remplit ce rôle . Ne chargez pas un modèle de vision

| Service | Ce qu'il fait | Taille du modèle | Accroître la vitesse SSK4 Utiliser quand M SK5 SSK6
|---------|-------------|------------|-------|-------------|
| `INerService` | BERT NER à partir du texte | ~430MB SMK3 \~50ms \| Vous avez déjà le texte |  | PDFs | , | Bases de données |, | Input d'utilisateur
| `IOcrService` | Tesseract OCR à partir d'images
| `IOcrNerPipeline` | OCR puis NER en un seul appel | Les deux modèles | S~150ms M| Vous avez des images et désirez des entités dans une seule étape R|
| `ITextRecognizerService` | RègleM SK1extraction basée sur le (dates , téléphones, etc.
| `IVisionService` | FlorenceM SK1 sous-titrage + OCR | ~450MB S| | ~1-3s | | Vous avez besoin d’une compréhension de l’image, et non pas seulement de la lecture du texte.

---


## NER du texte (Aucune image n'est requise)

Si vous avez déjà un texte (à partir de PDFsM SK1données de base de données ,entrée d'utilisateur), vous pouvez utiliser directement le NERMSC4 C'est la voie la plus rapide.

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `INerService` l'interface est simple - une méthode

```csharp
// From INerService.cs
public interface INerService
{
    Task<NerResult> ExtractEntitiesAsync(string text, CancellationToken ct = default);
}
```

Voici' comment l'utiliser dans votre propre service:

```csharp
public class MyService
{
    private readonly INerService _nerService;

    public MyService(INerService nerService)
    {
        _nerService = nerService;
    }

    public async Task ProcessDocumentAsync(string text)
    {
        var result = await _nerService.ExtractEntitiesAsync(text);

        foreach (var entity in result.Entities)
        {
            // entity.Label: "PER", "ORG", "LOC", or "MISC"
            // entity.Text: "John Smith"
            // entity.Confidence: 0.9996
            // entity.StartOffset / EndOffset: character positions in the source
        }
    }
}
```

Les modèles obtenus sont simples:

```csharp
// From NerResult.cs / NerEntity.cs
public class NerResult
{
    public string SourceText { get; init; } = string.Empty;
    public List<NerEntity> Entities { get; init; } = [];
}

public class NerEntity
{
    public string Text { get; init; } = string.Empty;     // "John Smith"
    public string Label { get; init; } = string.Empty;    // "PER", "ORG", "LOC", "MISC"
    public float Confidence { get; init; }                 // 0.0 to 1.0
    public int StartOffset { get; init; }                  // Where in the source text
    public int EndOffset { get; init; }                    // End position (exclusive)
}
```

Le premier appel télécharge le modèle BERT NER (~430MBMSC1 de HuggingFace. Les appels subséquents utilisent le modèle cached - le démarrage est instantanéM SK4

---


## Pipeline OCR + NER

Pour les images,, le pipeline gère la prétraitance , OCR, et NER en un seul appel `IOcrNerPipeline` combinés `IOcrService` et `INerService`:

```csharp
// From OcrNerPipeline.cs - the actual pipeline code
public async Task<OcrNerResult> ProcessImageAsync(string imagePath, CancellationToken ct = default)
{
    // Step 1: OCR (includes preprocessing automatically)
    var ocrResult = await _ocrService.ExtractTextAsync(imagePath, ct);

    if (string.IsNullOrWhiteSpace(ocrResult.Text))
        return new OcrNerResult
        {
            OcrResult = ocrResult,
            NerResult = new NerResult { SourceText = string.Empty }
        };

    // Step 2: NER on extracted text
    var nerResult = await _nerService.ExtractEntitiesAsync(ocrResult.Text, ct);

    return new OcrNerResult
    {
        OcrResult = ocrResult,
        NerResult = nerResult
    };
}
```

Utilisation:

```csharp
var pipeline = serviceProvider.GetRequiredService<IOcrNerPipeline>();

var result = await pipeline.ProcessImageAsync("invoice.png");

// What OCR found
var text = result.OcrResult.Text;           // The full extracted text
var confidence = result.OcrResult.Confidence; // 0.0 to 1.0

// What NER found in that text
foreach (var entity in result.NerResult.Entities)
{
    // [PER] John Smith, [ORG] Microsoft, [LOC] Seattle...
}
```

### Qu'est-ce qui se passe sous le cap?

```mermaid
flowchart LR
    IMG[Image bytes]
    PRE["ImageSharp<br>or OpenCV"]
    TESS["Tesseract<br>OCR"]
    TOK["WordPiece<br>Tokenize"]
    BERT["BERT NER<br>ONNX"]
    REC["Recognizers<br>(optional)"]
    OUT[Result]

    IMG --> PRE
    PRE --> TESS
    TESS --> TOK
    TOK --> BERT
    BERT --> REC
    REC --> OUT

    style PRE stroke:#f60,stroke-width:3px
    style BERT stroke:#f60,stroke-width:3px
    style REC stroke:#f60,stroke-width:2px,stroke-dasharray: 5 5
```

---


## Prétraitement de l'image

Partie 1 a eu des appels de Tesseract bruts . Dans la pratiqueMSC2 tant Tesserac que Florence-2 fonctionnent mieux avec les images prétraitéesM SK4 Le traitement préalable est **par défaut** mais entièrement facultatif - vous pouvez le désactiver avec `Preprocessing = "None"` dans la configuration ou `--preprocess none` sur le CLI.

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `ImagePreprocessor` utilisations **Graphique de l'image** (pure C

```csharp
// From ImagePreprocessor.cs - the actual preprocessing steps
public byte[] Preprocess(byte[] imageBytes, PreprocessingOptions? options = null)
{
    options ??= PreprocessingOptions.Default;
    using var image = Image.Load<Rgba32>(imageBytes);

    image.Mutate(ctx =>
    {
        // Step 1: Upscale small images (Tesseract wants 300+ DPI equivalent)
        if (options.EnableUpscale && (image.Width < options.MinWidth || image.Height < options.MinHeight))
        {
            var scale = Math.Max(
                (float)options.MinWidth / image.Width,
                (float)options.MinHeight / image.Height);
            scale = Math.Min(scale, options.MaxUpscaleFactor);
            ctx.Resize((int)(image.Width * scale), (int)(image.Height * scale),
                KnownResamplers.Lanczos3);
        }

        // Step 2: Grayscale (single channel = faster, more accurate)
        if (options.EnableGrayscale)
            ctx.Grayscale();

        // Step 3: Contrast boost (text stands out from background)
        if (options.EnableContrast && options.ContrastAmount != 1.0f)
            ctx.Contrast(options.ContrastAmount);

        // Step 4: Sharpen (crisp character edges)
        if (options.EnableSharpen)
            ctx.GaussianSharpen(options.SharpenSigma);
    });

    using var ms = new MemoryStream();
    image.SaveAsPng(ms);  // PNG = lossless, no additional artifacts
    return ms.ToArray();
}
```

Trois presets sont construits dans. `PreprocessingOptions` class les définit:

```csharp
// From ImagePreprocessor.cs
public static PreprocessingOptions Default => new();  // Grayscale + 1.5x contrast + sharpen

public static PreprocessingOptions Minimal => new()   // Grayscale only
{
    EnableContrast = false,
    EnableSharpen = false,
    EnableUpscale = false
};

public static PreprocessingOptions Aggressive => new() // For poor quality images
{
    ContrastAmount = 1.8f,
    SharpenSigma = 1.5f,
    MinWidth = 1024,
    MinHeight = 768,
    MaxUpscaleFactor = 4.0f
};
```

| Précéder | Quand utiliser | Ce qu'il fait S|
|--------|------------|--------------|
| `Default` | La plupart des images | Taille grise
| `Minimal` | Scans nettoyés | Seulement à l'échelle grise |
| `Aggressive` | Photos de mauvaise qualité MSC1 SMC2x contraste MSC3 apercevoir fortement SMC4 grande échelle |

### Prétraitement avancé avec OpenCV

Pour les documents gravement dégradés - les scans erronés , les photos bruyeuses, les pages historiques épuisées M SK3 le pipeline ImageSharp n’est pas suffisantMSC4 pas assezM SK5 activer `EnableAdvancedPreprocessing` pour passer à un pipeline OpenCV complet porté de [ImageSummarizer](https://github.com/scottgal/lucidrag).

La chaîne de préprocesseurs OpenCV comporte quatre étapes, chacune étant guidée par une évaluation automatique de la qualité:

```mermaid
flowchart LR
    IMG[Image]
    QA["Quality<br>Assess"]
    SK["Deskew"]
    DN["Denoise"]
    BIN["Binarize"]
    OUT[Clean image]

    IMG --> QA
    QA --> SK
    SK --> DN
    DN --> BIN
    BIN --> OUT

    style QA stroke:#f60,stroke-width:2px
```

**Évaluation de la qualité** (`ImageQualityAssessor`) mesure l'obscuritéM SK1 angle de triage , niveau du bruit, contrasteMSC4 uniformité de la luminositéMska5 et densité du texteM Ska6 Sur la base des résultatsMka7 il recommande les étapes à suivre pour appliquer Mska8 afin que les images propres échappent au traitement inutileMske9

**Deskew** (`SkewCorrector`) corrige les documents rotatifs à l'aide de trois méthodes : Détection des lignes d'écrasement

**Dénoise** (`NoiseReducer`) offre une brûlure Gaussiane ( rapide M SK2 filtre bilatéral

**Binariser** (`InkExtractor`) convertisseurs en noir propreM SK1 et - blanc à l'aide d'Otsu, seuil d'adaptationMSC4 Sauvola (pour les documents historiques dégradésMNK6 CLAHE SNK7 Otsu S(pour le contraste faibleMMK9 ou la suppression du fond morphologiqueMRK10

Activer dans la configuration ou sur le CLI:

```csharp
config.EnableAdvancedPreprocessing = true;
```

```bash
ocrner ocr damaged-scan.png -a
```

---


## Microsoft.Recognizers:RègleM SK2Extraction d'entités basées

BERT NER trouve des personnes, organismesM SK1 emplacements , et diverses entités. Mais certains données structurées MST4 dates MST5 numéros de téléphoneM ST6 courrielsM st7 URLs M st8 adresses IP Mst9 est mieux capté par les règles déterministes que par un réseau neuronalMst10

Activer `EnableRecognizers` pour ajouter un deuxième passe d'extraction en utilisant [Microsoft.Recognizers.Texte](https://github.com/microsoft/Recognizers-Text). Ce programme fonctionne **après** NER et extraits:

| Type | Exemples |
|------|----------|
| Date et heure MSC1 SMC2janvier MSC3 \MSC4 \ MSC5mars prochain MSc6 \ msC7semaine dernière MScs8 \msC9
| Numéro
| URL
| Téléphone
| Courrier électronique
| Adresse IP | SMK2 |

Le recognizer supporte plusieurs cultures (frM SK1us, fr -gbMSC4 deMNK5deMRK6 fr+-fr=, etc+MNK9 ainsi qu'il gère les localitésMMK10formats de date et conventions numériques spécifiquesMEK11

```csharp
config.EnableRecognizers = true;
config.RecognizerCulture = "en-us";
```

```bash
ocrner ner "John Smith joined Microsoft on January 15, 2024. Call 555-1234." -r
```

Les deux méthodes d’extraction se complètent. `OcrNerResult` Le modèle comprend maintenant une option `Signals` propriété:

```csharp
public class OcrNerResult
{
    public OcrResult OcrResult { get; init; } = new();
    public NerResult NerResult { get; init; } = new();
    public RecognizedSignals? Signals { get; init; }  // Only when EnableRecognizers = true
}
```

---


## Florence-2 Vision

Florence-2 est une approche complètement différente de Tesseract. où Tesserac est un moteur OCR spécialisé qui lit le texte caractère par caractère. **Modèle de vision** qui comprend l’ensemble de l’image - objets , scènes, personnesM SK3 et texteMSC4

```csharp
// From IVisionService.cs
public interface IVisionService
{
    Task<VisionCaptionResult> CaptionAsync(string imagePath, bool detailed = true,
        CancellationToken ct = default);
    Task<VisionOcrResult> ExtractTextAsync(string imagePath,
        CancellationToken ct = default);
    Task<bool> IsAvailableAsync(CancellationToken ct = default);
}
```

Utilisation:

```csharp
var vision = serviceProvider.GetRequiredService<IVisionService>();

// Generate a caption describing the image
var caption = await vision.CaptionAsync("photo.jpg", detailed: true);
if (caption.Success)
{
    // caption.Caption: "A man in a blue suit standing at a podium"
    // caption.DurationMs: how long it took
}

// Extract visible text using Florence-2's built-in OCR
var ocrResult = await vision.ExtractTextAsync("screenshot.png");
if (ocrResult.Success)
{
    // ocrResult.Text: the visible text Florence-2 detected
}
```

### Quand utiliser Which

| Case d'utilisation | Tesseract (`IOcrService`) | FlorenceM SK2 |`IVisionService`) |
|----------|--------------------------|-------------------------------|
| **Échantillonnage des documents** | Choix idéal - rapide M SK2 exact
| **Photos des panneaux** | Decent | Amélioré MSC2 comprend le contexte de la scène MSC3
| **Photos d'écran** | Bon | Bon
| **Caption de l'image** | Peut-on ' ne peut pas le faire
| **Accroître la vitesse** | Rapide (~100ms) | Plus lente MSC4sMSc5 |
| **Taille du modèle** |  ~4MB

Le point est le suivant : **Efficacité**: utiliser Tesseract pour l'extraction de documents et de textes (itM SK2s *la compréhension*.

Florence-2 autoM SK1downloads ses modèles (~450MBMSC3 lors de la première utilisation `{ModelDirectory}/florence2/`.

---


## Comment le pipeline NER fonctionne à l'interne

Le pipeline NER suit le même processus à trois étapes, décrit en détail dans [Partie 1](/blog/simple-ocr-ner-extraction): **tokeniser → inferr → décoder**. Partie 1 marche par tous les concepts MSC2 Tokenisation de WordPiece MSC3 Tensor inference d'ONNX SMC4 Décodage des balises BIO SMC5 confiance softmax sMC6 à partir de zéro avec un exemple constructif complet sMC7

Voici ce que le paquet ajoute au-delà de l'approche manuelle:

### Surveillance des défaillances

Partie 1's tokenizer convertit le texte en ID de cote . Le paquet's `BertNerTokenizer` aussi les pistes **Dérogations de caractères** - pour que vous sachiez exactement où chaque entité a été trouvée dans le texte source

```csharp
// From BertNerTokenizer.cs
// "John Smith works at Microsoft" becomes:
// [CLS] John Smith works at Micro ##soft [SEP] [PAD] ...
//
// Each token tracks its source position:
// "John"     → chars 0-4
// "Smith"    → chars 5-10
// "Micro"    → chars 20-29  (WordPiece splits "Microsoft")
// "##soft"   → chars 20-29  (same source range)
```

Voici comment : `NerEntity.StartOffset` et `EndOffset` travail - ils reprennent les positions exactes des caractères dans votre texte original

### Confidence-Extraction d'entités mobiles

Partie 1's décoder produit toutes les entités. Les filtres des paquets pendant le décodage - faibleM SK3 le bruit de confiance n'atteint jamais votre codeMSC4

```csharp
// From NerService.cs
private void FlushEntity(
    List<NerEntity> entities, string text,
    string type, int start, int end, float confidence)
{
    if (confidence < _config.MinConfidence) return;  // Filter low-confidence

    var entityText = text[start..end].Trim();
    if (string.IsNullOrWhiteSpace(entityText)) return;

    entities.Add(new NerEntity
    {
        Text = entityText,
        Label = type,
        Confidence = confidence,
        StartOffset = start,
        EndOffset = end
    });
}
```

---


## Auto-Décharger: Comment fonctionne-t-il

Tous les modèles sont téléchargés automatiquement lors de la première utilisation. Aucune installation manuelle n'est nécessaire.

```mermaid
flowchart TD
    CALL["First API call"]
    CHECK{"Files exist<br>in cache?"}
    YES[Use cached model]
    NO["Download to .tmp file"]
    MOVE["Atomic rename<br>.tmp → final"]

    CALL --> CHECK
    CHECK -->|Yes| YES
    CHECK -->|No| NO
    NO --> MOVE
    MOVE --> YES

    style NO stroke:#f60,stroke-width:3px
    style MOVE stroke:#090,stroke-width:3px
```

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `ModelDownloader` téléchargements de HuggingFace (NER modelM SK1 et GitHub (tessdata). Il utilise un `.tmp` Modèle - si un téléchargement est interrompu, aucun fichier corrompu n'est laissé derrière

```csharp
// From ModelDownloader.cs - atomic download pattern
await using var fileStream = new FileStream(tempPath, FileMode.Create,
    FileAccess.Write, FileShare.None, 81920, true);
// ... stream download to .tmp file ...
await fileStream.FlushAsync(ct);
fileStream.Close();

File.Move(tempPath, localPath, overwrite: true);  // Atomic rename
```

Emplacement du cache par défaut: `{AppBaseDir}/models/ocrner/`

```text
models/ocrner/
  ner/
    model.onnx      (~430MB - BERT NER)
    vocab.txt       (~230KB - WordPiece vocabulary)
    config.json     (~1KB - label mapping)
  tessdata/
    eng.traineddata (~4MB - English OCR data)
  florence2/
    ...             (~450MB - Vision model files)
```

---


## Architecture

Tout est un seul tonne avec une initialisation lente. Ressources coûteuses (ONNX `InferenceSession`, `TesseractEngine`, FlorenceM SK1 modèle ) sont créés une fois à la première utilisation et réutilisés pendant toute la durée de vie de l'application.

```mermaid
flowchart TD
    DI["AddOcrNer()"]

    DI --> MD["ModelDownloader<br>(singleton)"]
    DI --> PP["ImagePreprocessor<br>(singleton)"]
    DI --> CV["OpenCvPreprocessor<br>(singleton)"]
    DI --> NER["NerService<br>(singleton)"]
    DI --> OCR["OcrService<br>(singleton)"]
    DI --> PIPE["OcrNerPipeline<br>(singleton)"]
    DI --> REC["TextRecognizerService<br>(singleton)"]
    DI --> VIS["VisionService<br>(singleton)"]

    MD --> NER
    MD --> OCR
    PP --> OCR
    CV --> OCR
    NER --> PIPE
    OCR --> PIPE
    REC --> PIPE

    style DI stroke:#090,stroke-width:3px
```

Sécurité des fils: tous les services utilisés `SemaphoreSlim` pour l'initialisation. Plusieurs threads appelant le service simultanément lors de la première utilisation ne déclencheront qu'un seul téléchargement

```csharp
// From NerService.cs - lazy init pattern used by all services
private async Task EnsureInitializedAsync(CancellationToken ct)
{
    if (_initialized) return;           // Fast path: already loaded

    await _initLock.WaitAsync(ct);      // Only one thread enters
    try
    {
        if (_initialized) return;       // Double-check after lock

        var paths = await _downloader.EnsureNerModelAsync(ct);
        _tokenizer = new BertNerTokenizer(paths.VocabPath, _config.MaxSequenceLength);
        _session = new InferenceSession(paths.ModelPath, sessionOptions);
        _initialized = true;
    }
    finally { _initLock.Release(); }
}
```

---


## Outil CLI

Le répertoire comprend un outil de ligne de commande- construit avec [Spectre.Console](https://spectreconsole.net/). Il est conçu comme un point de départ pour le succès.

### Démarrage rapide

```bash
# NER from text (auto-detected)
ocrner "John Smith works at Microsoft in Seattle"

# OCR from an image (auto-detected)
ocrner invoice.png

# Explicit commands
ocrner ner "Marie Curie won the Nobel Prize in Stockholm"
ocrner ocr scan.png
ocrner caption photo.jpg
```

**Routage intelligent**: l'auto de CLIM SK1 détecte votre intention . De `Program.cs`:

```csharp
// From Program.cs - smart routing logic
if (IsImageFile(args2[0]) || IsGlobPattern(args2[0]) || Directory.Exists(args2[0]))
{
    args2 = ["ocr", .. args2];   // Image file → ocr command
}
else
{
    args2 = ["ner", .. args2];   // Text string → ner command
}
```

Si vous passez une chaîne de texte, il s’agit d’un NER. Si vous laissez passer un fichier d’imagesM SK2 globe , ou un répertoireMSC4 il est un OCR MST5 NER~MST6 Aucun commande n’est requiseMst7

### Trois commandes

| Commande | Ce qu'il fait | moteur | vitesse SMK4
|---------|-------------|--------|-------|
| `ner <text>` | Extraire des entités du texte | BERT N.-É.
| `ocr <path>` | OCR + NER à partir d'images
| `caption <path>` | Caption d'images + OCR facultatif | FlorenceM SK3 SSK4ONNX |

**Tesseract est le moteur OCR par défaut.** car il est plus rapide et optimisé pour le texte du document's 5-10x FlorenceM SK3 s'adresse aux personnes qui ont besoin d'une compréhension de l'image.

### Résultats réels

Voici les résultats réels de l’exploitation du CLI par rapport aux documents d’échantillonnage réels.

**NER du texte:**

```bash
ocrner ner "Marie Curie won the Nobel Prize in Stockholm"
```

```text
╭──────┬─────────────┬────────────┬──────────╮
│ Type │ Entity      │ Confidence │ Position │
├──────┼─────────────┼────────────┼──────────┤
│ PER  │ Marie Curie │ 100%       │ 0-11     │
│ MISC │ Nobel Prize │ 100%       │ 20-31    │
│ LOC  │ Stockholm   │ 100%       │ 35-44    │
╰──────┴─────────────┴────────────┴──────────╯
```

**NER avec des reconnaissants** - combinaison des entités BERT avec la règle-extraction de signaux basée sur :

```bash
ocrner ner "Shelby Lucier from SCS Agency in Cambridge, UK sent an invoice on 13/02/15. Call 07981423683." -r
```

```text
╭──────┬───────────────┬────────────┬──────────╮
│ Type │ Entity        │ Confidence │ Position │
├──────┼───────────────┼────────────┼──────────┤
│ PER  │ Shelby Lucier │ 100%       │ 0-13     │
│ ORG  │ SCS Agency    │ 100%       │ 19-29    │
│ LOC  │ Cambridge     │ 100%       │ 33-42    │
│ LOC  │ UK            │ 100%       │ 44-46    │
╰──────┴───────────────┴────────────┴──────────╯

── Recognized Signals ─────────────────────────
  Type       Text          Details
  DateTime   13/02/15      datetimeV2.date
  Phone      07981423683
```

BERT identifie les personnes, organismes, et les emplacements . Les récepteurs détectent la date et le numéro de téléphone M SK3 des patrons structurés qu’un réseau neuronal ne serait pas fiable d’extraire

**OCR à partir d'un document scanné** (une lettre des actionnaires d’AmazonM SK1scannée avec un trou -marques ponctuelles):

```bash
ocrner ocr shareholder-letter.jpg -q
```

```text
╭──────┬───────────────┬────────────┬──────────╮
│ Type │ Entity        │ Confidence │ Position │
├──────┼───────────────┼────────────┼──────────┤
│ ORG  │ Amazon        │ 87%        │ 285-291  │
│ PER  │ Jeff          │ 99%        │ 293-297  │
│ ORG  │ AWS           │ 95%        │ 984-987  │
│ LOC  │ America       │ 98%        │ 2315-2322│
╰──────┴───────────────┴────────────┴──────────╯
OCR Confidence: 89%
```

Tesseract extrait près de -le texte verbal de la lettre scannée à l’adresse suivante : 89%confidenceM SK2 et NER identifie correctement Amazon,Jeff (BezosMST5AWSMSC6et Amérique du NordMSL7

### Tesseract vs Florence-2: Comparaison réelle

La même lettre d’actionnaire scannée traitée par les deux moteurs:

| | Tesseract (`ocrner ocr`) | FlorenceM SK2 |`ocrner caption --ocr`) |
|---|---|---|
| **Accroître la vitesse** | ~200ms | ≥~14s MSC4
| **Précision de l'OCR** | PrÃ ̈sM SK1verbatim, 89% confiance.
| **Texte clé** | " Au cours des deux dernières années à AmazonM SK3 j’ai eu l’occasion' de m’exprimer sur les questions qui me sont posées.
| **Entités du NER** | Jeff (PER), Amazon MSC3ORGM SK4 AWS MSC5ORG\), Amérique SMC7LOCMSC8 SMC9 NSCM10A ESMC11le texte trop endommagé pour être fiable NERS MC12 | SMC13
| **Caption** | NM SK1A

Florence-2 est un **vision** Modèle - il comprend les scènes , les objets M SK2 et les relations spatiales . Il n'a jamais été conçu pour rivaliser avec Tesseract lors de la lecture du texte d'un document MSC4 Utiliser quand vous avez besoin d'image *la compréhension* (qu'est-ce queM SK1qui se trouve sur cette photo ?), pas de texte *extraction* (que dit ce document?

### Outils JSON pour l'automatisation & LLM

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `--json` flag outputs structured JSON to stdout with all logging suppressed - designed for piping into other tools , LLM function callingM SK2 or automation scripts:

```bash
ocrner ner "Shelby Lucier from SCS Agency in Cambridge, UK sent an invoice on 13/02/15. Call 07981423683." -r --json
```

```json
{
  "command": "ner",
  "success": true,
  "sourceText": "Shelby Lucier from SCS Agency in Cambridge, UK...",
  "entityCount": 4,
  "entities": [
    { "type": "PER", "text": "Shelby Lucier", "confidence": 0.9996, "startOffset": 0, "endOffset": 13 },
    { "type": "ORG", "text": "SCS Agency", "confidence": 0.999, "startOffset": 19, "endOffset": 29 },
    { "type": "LOC", "text": "Cambridge", "confidence": 0.9975, "startOffset": 33, "endOffset": 42 },
    { "type": "LOC", "text": "UK", "confidence": 0.9991, "startOffset": 44, "endOffset": 46 }
  ],
  "signals": {
    "dateTimes": [{ "text": "13/02/15", "typeName": "datetimeV2.date" }],
    "phoneNumbers": [{ "text": "07981423683" }]
  }
}
```

Le CLI est donc utilisable en tant que **Outils** pour les LLM et les agents. Un LLM peut appeler `ocrner ner "..." --json`, étudier la réponse JSON , et expliquer sur les entités structurées `jq`, feed à un cadre d'agents, ou lire de n'importe quelle langue :

```bash
# Pipe to jq for quick filtering
ocrner ocr invoice.png --json | jq '.results[0].entities[] | select(.type == "PER")'

# Use from Python, Node, or any language that can shell out
echo "John Smith at Microsoft" | ocrner ner --json
```

Pour sauvegarder à un fichier en place, utilisez `-o` avec un `.json` extension - les mêmes données structurées , écrites sur le disque:

```bash
ocrner ocr "scans/*.png" -o results.json
```

### Traitement par lots

Tracer plusieurs images avec des patrons globaux ou des répertoires:

```bash
# All PNGs in a directory
ocrner ocr "scans/*.png" -o results.json

# All images in a folder
ocrner ocr ./documents/

# Batch captioning with Florence-2
ocrner caption "photos/*.jpg" --ocr -o captions.md
```

### Toutes les options de l'IDC

| drapeau | S'applique à MSC2 Description SMC3
|------|------------|-------------|
| `--json` | `ner`, `ocr`, `caption` | JSON structuré à stdout (implies `--quiet`, supprime tout enregistrement
| `-c` | `ner`, `ocr` | Seuil minimal de confiance des entités (0.0-1.0)
| `--language` | `ocr` | Langue Tesseract (par exemple `eng`, `fra`) |
| `--max-tokens` | `ner`, `ocr` | Durée maximale de la séquence BERT |
| `--model-dir` | `ner`, `ocr`, `caption` | Supprimer le répertoire de cache modèle |
| `-p`, `--preprocess` | `ocr`, `caption` | Prédéfinition de prétraitement: `none`, `minimal`, `default`, `aggressive` |
| `-a`, `--advanced-preprocess` | `ocr`, `caption` | Utiliser le prétraitement OpenCV (deskew, denoiseM SK3 binarizeMSC4
| `-r`, `--recognizers` | `ner`, `ocr` | Activer la règle-extraction basée sur (datesM SK3numéro(s)
| `--culture` | `ner`, `ocr` | Culture du récepteur `en-us`, `de-de` (default: `en-us`) |
| `--brief` | `caption` | Gérer une caption plus courte, moins détaillée |
| `-q`, `--quiet` | `ner`, `ocr`, `caption` | Mode silencieux ( sortie de console réduiteM SK2
| `-o` | `ner`, `ocr`, `caption` | Voie du fichier de sortie (`.txt`, `.md`, `.json`) |
| `--ocr` | `caption` | Faire également fonctionner l’OCR pendant le commandement de captions |
| `--ner` | `caption` | Extraire le NER du texte OCR ( simplifie `--ocr`) |

---


## Performance: Modèles quantifiés et ce qu’il faut faireM SK1 Suivant

Le modèle NER actuel est l’exactitude totale de la valeur - `protectai/bert-base-NER-onnx` (~430MBM SK1 Dans de nombreux cas d'utilisation - particulièrement sur les ressources- machines restreintes ou lorsqu'il s'agit du traitement de volumes élevés **évaluation quantifiée** La version du même modèle serait significativement plus rapide avec une perte minimale d’exactitude.

OnNX Runtime appuie l’INT8 quantisation hors de la boîte , qui réduit habituellement la taille du modèle par M SK2x et améliore la vitesse d’inférence par \2-3x sur le CPU. Ceci figure dans la feuille de route `NerModelRepo` config option supporte déjà le pointage vers une autre repo HuggingFace, alors quand un modèle quantifié est publié vous'd juste changerM SK2

```json
{
  "OcrNer": {
    "NerModelRepo": "protectai/bert-base-NER-onnx-quantized"
  }
}
```

L'architecture est conçue pour ce - échanger le modèle , conserver la même API

---


## L’image la plus grande: où cela convient

Ce paquet est un **pipeline unique-**: un moteur OCR , un modèle NER M SK2 un model de vision optionnel . Il est conçu pour être simple et efficace dans le cas courant MSC5

Pour des scénarios plus complexes - lire le texte de *Toute chose* (notes manuscrites ,photos de tableaux blancs,coût faibleM SK3catégories d'imagerie de qualité ●),avec multi ●- ●Consens OCR de l'engine ●MSC6 ●Matching fuzzy ●M SK7 ●Extraction structurée ●MST8 ●Voir le pipeline en entier à [***lucide*RAG**](https://www.lucidrag.com). C'est là où se trouve la version multi-phase de ce travail de production -de classeM SK3-

### Qu'est-ce's Suivant: LLM multimodal

Florence-2 est le plafond actuel de la vision locale dans ce paquet. **LLM multimodal** - un modèle qui peut voir une image *et* expliquez-en en langage naturel. Au lieu d’un OCR distinct + étapes NERM SK2 vous 'dvoyez l’image directement et demandez une extraction structurée

Voici ce que l’API pourrait ressembler à :

```csharp
// Hypothetical future IMultimodalService
public interface IMultimodalService
{
    Task<StructuredExtractionResult> ExtractAsync(
        string imagePath,
        string prompt = "Extract all people, organizations, and locations from this image. Return as JSON.",
        CancellationToken ct = default);
}

// Usage
var multimodal = serviceProvider.GetRequiredService<IMultimodalService>();
var result = await multimodal.ExtractAsync("business-card.jpg");

// result.Entities: [{ "John Smith", PER }, { "Acme Corp", ORG }, { "New York", LOC }]
// result.RawText: "John Smith, VP Engineering, Acme Corp, New York, NY 10001"
// result.Summary: "Business card for John Smith at Acme Corp in New York"
```

Petits modèles multimodaux locaux (comme [Phi-3.5-vision](https://huggingface.co/microsoft/Phi-3.5-vision-instruct) ou [LLaVA](https://llava-vl.github.io/)) sont devenus suffisamment bons pour celaM SK1 Le commerce -off est toujours le même M SK3 modèle plus grand = plus intelligent mais plus lente MSC5 La bonne option dépend de votre budget de latence et des exigences en matière d’exactitude

```mermaid
flowchart LR
    subgraph Staged["Staged Approach: Pick Your Level"]
        T1["Tesseract OCR<br>4MB | ~100ms<br>Text extraction"]
        T2["BERT NER<br>430MB | ~50ms<br>Entity extraction"]
        T3["Florence-2<br>450MB | ~1-3s<br>Image understanding"]
        T4["Multimodal LLM<br>2-8GB | ~5-30s<br>Full reasoning"]
    end

    T1 --> T2
    T2 --> T3
    T3 -.->|"future"| T4

    style T1 stroke:#090,stroke-width:2px
    style T2 stroke:#090,stroke-width:2px
    style T3 stroke:#f60,stroke-width:2px
    style T4 stroke:#999,stroke-width:2px,stroke-dasharray: 5 5
```

Chaque niveau ajoute des capacités au prix de la taille et de la latence. [***lucide*RAG**](https://www.lucidrag.com) est la position.

---


## Ressources

**Ce paquet**:

- **[Mostlylucid.OcrNer sur NuGet](https://www.nuget.org/packages/Mostlylucid.OcrNer)** - Installer
- **[Code de source](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.OcrNer)** - Consulter la mise en œuvre

**Partie 1**:

- **[Extraction simple de la fonction OCR et NER](/blog/simple-ocr-ner-extraction)** - Le tutoriel qui explique chaque pièce

**Dépendances**:

- **[Tesseract.NET](https://github.com/charlesw/tesseract)** - CM SK1 enveloppe pour Tesseract OCR
- **[BERT-base-NER ONNX](https://huggingface.co/protectai/bert-base-NER-onnx)** - Le modèle NER
- **[Florence-2](https://www.nuget.org/packages/Florence2)** - Vision Model NuGet package
- **[Graphique de l'image](https://sixlabors.com/products/imagesharp/)** - Traitement d'images sur une plate-forme
- **[OpenCvSharp4](https://github.com/shimat/opencvsharp)** - Enveloppeur OpenCV pour le prétraitement avancé
- **[Microsoft.Recognizers.Texte](https://github.com/microsoft/Recognizers-Text)** - Règle - extraction d'entités fondée
- **[Le temps de fonctionnement d'ONNX](https://onnxruntime.ai/)** - Inférence du modèle de plate-forme

**Articles connexes**:

- **[Le pipeline Three-Tier OCR](/blog/constrained-fuzzy-image-ocr-pipeline)** - Lorsque vous avez besoin de plus que d'une simple OCR
- **[RAG réduit](/blog/reduced-rag-concept)** - Lorsque les entités extraites correspondent à l’ensemble
- **[*lucide*RAG](https://www.lucidrag.com)** - Le pipeline de production à phases multiples