Vai al contenuto principale
Nel caso del riconoscimento a livello di field, vengono riconosciuti brevi frammenti di testo per acquisire dati da determinati field. La qualità del riconoscimento è fondamentale in questo scenario. Questo scenario può essere utilizzato anche come parte di scenari più complessi in cui occorre estrarre dati significativi dai documenti (ad esempio, per acquisire dati da documenti cartacei in sistemi informativi e database oppure per classificare e indicizzare automaticamente i documenti nei sistemi di gestione documentale). In questo scenario, il sistema riconosce diverse righe di testo solo in alcuni field oppure l’intero testo in una piccola immagine. Il sistema calcola un indice di affidabilità per ogni carattere riconosciuto. Gli indici di affidabilità possono quindi essere utilizzati durante la verifica dei risultati del riconoscimento. Inoltre, il sistema può memorizzare più varianti di riconoscimento per parole e caratteri nel testo, che possono poi essere utilizzate in algoritmi di voto per migliorare la qualità del riconoscimento. L’elaborazione di piccoli frammenti di testo in questo scenario differisce per alcuni aspetti dagli stessi passaggi in altri scenari:
  1. Pre-elaborazione di immagini scansionate o fotografie
Le immagini da riconoscere possono includere segni e rumore di fondo, entrambi in grado di ostacolare il riconoscimento. Per questo motivo, in questa fase vengono rimossi eventuali segni indesiderati e il rumore di fondo.
  1. Riconoscimento di piccoli frammenti di testo
Quando si riconoscono piccoli frammenti di testo, il tipo di dati da riconoscere è noto in anticipo. Pertanto, la qualità del riconoscimento può essere migliorata tramite l’uso di dizionari esterni, espressioni regolari, lingue di riconoscimento personalizzate e alfabeti, nonché imponendo restrizioni sul numero di caratteri in una string. I field di testo possono contenere testo stampato, scritto a stampatello e scritto a mano.
  1. Utilizzo dei dati riconosciuti
Questo scenario richiede la massima accuratezza di riconoscimento per ridurre al minimo il lavoro di verifica dei dati. Il sistema può calcolare un indice di affidabilità per ogni parola o carattere riconosciuto e fornire più varianti di riconoscimento, tra le quali diversi motori possono quindi scegliere il candidato migliore applicando algoritmi di voto.

Implementazione dello scenario

Gli esempi di codice forniti in questo argomento sono specifici per Windows.
Di seguito è riportata una descrizione dettagliata del metodo consigliato per l’utilizzo di ABBYY FineReader Engine 12 in questo scenario. Il metodo suggerito utilizza le impostazioni di elaborazione ritenute più appropriate per questo scenario.
Per iniziare a lavorare con ABBYY FineReader Engine, è necessario creare l’oggetto Engine. L’oggetto Engine è l’oggetto di livello superiore nella gerarchia degli oggetti di ABBYY FineReader Engine e fornisce varie impostazioni globali, alcuni metodi di elaborazione e metodi per la creazione degli altri oggetti.Per creare l’oggetto Engine, è possibile utilizzare la funzione InitializeEngine. Vedere anche altri modi per caricare l’oggetto Engine (Win).

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // Inizializzare queste variabili con il percorso completo di FREngine.dll, il Customer Project ID,
        // e, se applicabile, il percorso del file token della licenza online e la password della licenza online
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Caricare la libreria FREngine.dll
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("Impossibile caricare " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Impossibile trovare la funzione InitializeEngine");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Impossibile trovare la funzione DeinitializeEngine");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Impossibile trovare la funzione DllCanUnloadNow");
            }
            // Convertire i puntatori in delegati
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Chiamare la funzione InitializeEngine
            // passando il percorso del file della licenza online e la relativa password
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // Liberare la libreria FREngine.dll
            engine = null;
            // Eliminare tutti gli oggetti prima della chiamata a FreeLibrary
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Funzioni di Kernel32.dll
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // Funzioni di FREngine.dll
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine(string customerProjectId, string licensePath, 
        string licensePassword, string tempFolder, string dataFolder, bool isSharedCPUCoresMode, 
        ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // Variabili private
    private FREngine.IEngine engine = null;
    // Handle di FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

// Inizializzare queste variabili con il percorso di FREngine.dll, il Customer Project ID di FineReader Engine,
// e, se applicabile, il percorso del token della licenza online e la password della licenza online
wchar_t* FreDllPath;
wchar_t* CustomerProjectId;
wchar_t* LicensePath;  // se non si utilizza una licenza online, assegnare stringhe vuote a queste variabili
wchar_t* LicensePassword;
// HANDLE per FREngine.dll
static HMODULE libraryHandle = 0;
// Oggetto globale FineReader Engine
FREngine::IEnginePtr Engine;
void LoadFREngine()
{
    if( Engine != 0 ) {
    // Già caricato
    return;
    }
    // Primo passaggio: caricare FREngine.dll
    if( libraryHandle == 0 ) {
        libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
        if( libraryHandle == 0 ) {
            throw L"Errore durante il caricamento di ABBYY FineReader Engine";
        }
    }
    // Secondo passaggio: ottenere l'oggetto Engine
    typedef HRESULT ( STDAPICALLTYPE* InitializeEngineFunc )( BSTR, BSTR, BSTR, BSTR, 
        BSTR, VARIANT_BOOL, FREngine::IEngine** );
    InitializeEngineFunc pInitializeEngine =
    ( InitializeEngineFunc )GetProcAddress( libraryHandle, "InitializeEngine" );
    if( pInitializeEngine == 0 || pInitializeEngine( CustomerProjectId, LicensePath, 
        LicensePassword, L"", L"", VARIANT_FALSE, &Engine ) != S_OK ) {
    UnloadFREngine();
    throw L"Errore durante il caricamento di ABBYY FineReader Engine";
    }
}
Le impostazioni più adatte possono essere selezionate usando il metodo LoadPredefinedProfile dell’oggetto Engine. Questo metodo riceve il nome del profilo come parametro di input. Le impostazioni più adatte possono essere selezionate usando il profilo predefinito denominato FieldLevelRecognition. Per ulteriori informazioni sui profili, vedere Uso dei profili.

C#

// Carica un profilo predefinito
engine.LoadPredefinedProfile("FieldLevelRecognition");

C++ (COM)

// Carica un profilo predefinito
Engine->LoadPredefinedProfile( L"FieldLevelRecognition" );
Se desideri modificare le impostazioni usate per l’elaborazione, utilizza i corrispondenti oggetti parametro. Per ulteriori informazioni, consulta la sezione Ottimizzazione aggiuntiva riportata di seguito.
ABBYY FineReader Engine fornisce un oggetto FRDocument per elaborare documenti multipagina. Per caricare le immagini di un documento e pre-elaborarle, è necessario creare l’oggetto FRDocument e aggiungervi le immagini. Puoi eseguire una delle seguenti operazioni:

C#

// Crea l'oggetto FRDocument da un file immagine
FREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );

C++ (COM)

// Apre un file immagine e crea l'oggetto FRDocument
FREngine::IFRDocumentPtr frDocument = Engine->CreateFRDocumentFromImage( L"C:\\MyImage.tif", 0 );
Ora devi creare blocchi che contengano i field e, per ciascuno di essi, specificare il tipo di blocco e le caratteristiche note dei dati contenuti al suo interno.Esegui l’analisi del layout del documento usando il metodo Analyze, oppure aggiungi manualmente i blocchi che contengono i field da riconoscere. Per istruzioni, consulta Uso di Layout e Block.Per ogni field, puoi ora specificarne i parametri di riconoscimento. Ad esempio, se un field contiene testo, usa la proprietà ITextBlock::RecognizerParams:
  • imposta il tipo di testo mediante la proprietà TextTypes dell’oggetto RecognizerParams. Ad esempio, se il field contiene cifre scritte nel formato del codice postale, usa il tipo di testo TT_Index.
  • imposta la lingua usando il metodo SetPredefinedTextLanguage. L’uso di lingue predefinite speciali (solo Windows) può essere utile se conosci il tipo di informazioni contenute nel field. Ad esempio, se il field contiene un indirizzo negli Stati Uniti, seleziona la lingua predefinita English_US_Address. In questo modo il testo verrà riconosciuto in modo più affidabile.
  • imposta le proprietà SaveCharacterRecognitionVariants e SaveWordRecognitionVariants dell’oggetto RecognizerParams se devi usare le varianti di riconoscimento per un’ulteriore verifica del risultato, come descritto più avanti nel passaggio 6. Tieni presente che questa impostazione non è disponibile per testi manoscritti o in stampatello.
Per ulteriori dettagli sul riconoscimento di diversi tipi di field, consulta le sezioni Riconoscimento dei segni di spunta, Riconoscimento di testi scritti a mano, Riconoscimento di Barcode e Riconoscimento di parole con spazi.

C#

// Analizza il layout del documento
frDocument.Analyze( null, null, null );
// Supponiamo di sapere che il primo blocco
// nel layout contiene un indirizzo negli Stati Uniti
FREngine.ITextBlock addressBlock = frDocument.Pages[0].Layout.Blocks[0].GetAsTextBlock();
FREngine.IRecognizerParams paramsAddressBlock = addressBlock.RecognizerParams;
paramsAddressBlock.SetPredefinedTextLanguage( "English_US_Address" );
// Abilita la raccolta delle varianti di riconoscimento
paramsAddressBlock.SaveCharacterRecognitionVariants = true;
paramsAddressBlock.SaveWordRecognitionVariants = true;
// Configura allo stesso modo le proprietà degli altri blocchi del layout
...

C++ (COM)

// Analizza il layout del documento
frDocument->Analyze( 0, 0, 0 );
// Supponiamo di sapere che il primo blocco
// nel layout contiene un indirizzo negli Stati Uniti
FREngine::ILayoutBlocksPtr layoutBlocks = frDocument->Pages->Item( 0 )->Layout->Blocks;
FREngine::IRecognizerParamsPtr paramsAddressBlock = layoutBlocks->Item( 0 )->GetAsTextBlock()->RecognizerParams;
paramsAddressBlock->SetPredefinedTextLanguage( L"English_US_Address" );
// Abilita la raccolta delle varianti di riconoscimento
paramsAddressBlock->SaveCharacterRecognitionVariants = VARIANT_TRUE;
paramsAddressBlock->SaveWordRecognitionVariants = VARIANT_TRUE;
// Configura allo stesso modo le proprietà degli altri blocchi del layout
...
Poiché il layout del documento è già stato analizzato e da te ulteriormente modificato, non richiamare i metodi di analisi. Usa il metodo Recognize, che esegue il riconoscimento e la sintesi delle pagine per tutte le pagine del documento. In questo scenario, devi estrarre i dati dai field e non esportare il documento riconosciuto; pertanto, non avrai bisogno della sintesi del documento.

C#

// Riconosci il documento
// Non è necessario specificare parametri perché sono impostati dal profilo di elaborazione
frDocument.Recognize( null, null );

C++ (COM)

// Riconosci il documento
// Non è necessario specificare parametri perché sono impostati dal profilo di elaborazione
frDocument->Recognize( 0, 0 );
Usa l’oggetto Text per accedere al frammento di testo riconosciuto (puoi ottenere questo oggetto per un blocco di testo tramite la proprietà ITextBlock::Text). Usa la proprietà Paragraphs per ottenere la raccolta di paragrafi nel frammento e il metodo IParagraphs::Item per accedere ai singoli paragrafi. La proprietà IParagraph::Text consente di accedere al testo riconosciuto di un paragrafo.Puoi usare IParagraph::Words per ottenere la raccolta di parole in un paragrafo. Usa il metodo IWords::Item per accedere alle singole parole della raccolta. La proprietà IWord::Text restituisce la riga che contiene la parola riconosciuta. Usa il metodo GetRecognitionVariants dell’oggetto Word o il metodo GetWordRecognitionVariants dell’oggetto Paragraph per ottenere le varianti di riconoscimento di una parola.Puoi accedere agli attributi dei singoli caratteri tramite il metodo GetCharParams dell’oggetto Paragraph. Questo metodo fornisce accesso all’oggetto CharParams, che contiene i parametri del carattere riconosciuto. Le varianti di riconoscimento di un carattere sono accessibili tramite la proprietà ICharParams::CharacterRecognitionVariants.Per informazioni dettagliate sull’utilizzo del testo, vedi Lavorare con il testo. Per informazioni sull’uso del motore negli algoritmi di voto, vedi Uso di Voting API.Dopo aver terminato di lavorare con l’oggetto FRDocument, rilascia tutte le risorse utilizzate da questo oggetto. Usa il metodo IFRDocument::Close.
Dopo aver terminato il lavoro con ABBYY FineReader Engine, è necessario scaricare l’oggetto Engine. Per farlo, usa la funzione esportata DeinitializeEngine.

C#

public class EngineLoader : IDisposable
{
    // Scarica FineReader Engine
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine non è stato caricato
            return;
        }
        engine = null;
        // Elimina tutti gli oggetti prima della chiamata a FreeLibrary
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        int hresult = deinitializeEngine();
 
        hresult = dllCanUnloadNow();
        if (hresult == 0)
        {
            FreeLibrary(dllHandle);
        }
        dllHandle = IntPtr.Zero;
        initializeEngine = null;
        deinitializeEngine = null;
        dllCanUnloadNow = null;
        // solleva un'eccezione dopo la pulizia
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Funzioni di Kernel32.dll
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // Funzioni di FREngine.dll
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine( string customerProjectId, string LicensePath, string LicensePassword, , , , ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // variabili private
    private FREngine.IEngine engine = null;
    // Handle di FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

void UnloadFREngine()
{
 if( libraryHandle == 0 ) {
  return;
 }
 // Rilascia l'oggetto Engine
 Engine = 0;
 // Deinizializza FineReader Engine
 typedef HRESULT ( STDAPICALLTYPE* DeinitializeEngineFunc )();
 DeinitializeEngineFunc pDeinitializeEngine =
  ( DeinitializeEngineFunc )GetProcAddress( libraryHandle, "DeinitializeEngine" );
 if( pDeinitializeEngine == 0 || pDeinitializeEngine() != S_OK ) {
  throw L"Errore durante lo scaricamento di ABBYY FineReader Engine";
 }
 // Ora è possibile liberare in sicurezza la libreria FREngine.dll
 FreeLibrary( libraryHandle );
 libraryHandle = 0;
}

Risorse richieste

Puoi usare il file FREngineDistribution.csv per creare automaticamente un elenco dei file necessari al corretto funzionamento della tua applicazione. Per l’elaborazione con questo scenario, seleziona nella colonna 5 (RequiredByModule) i seguenti valori: Core Core.Resources Opening Opening, Processing Processing Processing.OCR Processing.OCR, Processing.ICR Processing.OCR.NaturalLanguages Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages Se modifichi lo scenario standard, aggiorna di conseguenza i moduli richiesti. Devi inoltre specificare le lingue dell’interfaccia, le lingue di riconoscimento ed eventuali funzionalità aggiuntive usate dalla tua applicazione (ad esempio, Opening.PDF se devi aprire file PDF, oppure Processing.OCR.CJK se devi riconoscere testi in lingue CJK). Per ulteriori dettagli, consulta Working with the FREngineDistribution.csv File.

Ottimizzazione aggiuntiva

Di seguito sono riportate le sezioni della guida in cui puoi trovare ulteriori informazioni sulla configurazione dei parametri per le varie fasi di elaborazione:

Vedi anche

Implementazione degli scenari di utilizzo di base