> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Document Comparison

> Compare un documento en papel o su imagen con una copia mediante la API de comparación de documentos de ABBYY FineReader Engine: detecte cambios en el texto insertado, eliminado o modificado.

Al trabajar con documentos en papel, es necesario encontrar y corregir errores o cambios realizados intencionadamente. Use la API de comparación de documentos para localizar estos cambios de forma rápida y eficaz.

Este escenario se utiliza para comparar documentos de especial importancia, como contratos y documentación bancaria, con sus copias. El resultado de la comparación contiene información sobre las diferencias en el tipo de contenido (solo texto), el tipo de modificación (eliminado, insertado o modificado) y su ubicación en el original y en la copia. Puede obtener la lista de diferencias detectadas o la región de cualquier cambio, y guardar el resultado de la comparación en un archivo externo para su posterior procesamiento o almacenamiento a largo plazo.

Para comparar documentos o páginas, los archivos obtenidos mediante escaneo o guardados en formato electrónico suelen pasar por varias etapas de procesamiento, cada una con sus propias particularidades:

1. Preprocesamiento de archivos escaneados o imágenes

   Los archivos y sus copias requieren cierto preprocesamiento antes del reconocimiento si presentan defectos o anotaciones hechas intencionadamente, como firmas o sellos.

2. Reconocimiento con restauración completa de la estructura y el formato del documento

   Al reconocer un documento, se identifican varios elementos de diseño (texto, tablas, imágenes, separadores, etc.) del documento. Durante la síntesis del documento, se restaura su estructura lógica, mientras que la síntesis de la página permite restaurar por completo el formato del documento (fuentes, estilos, etc.)

3. Comparación de documentos o páginas

   Para comparar documentos o páginas con sus copias, use archivos reconocidos con ABBYY FineReader Engine. Puede usar dos versiones de un documento en formatos distintos. Tras la comparación, obtendrá un resultado con la lista de cambios; úselo para recuperar información sobre la ubicación de esos cambios. Si utiliza verificación manual, use esta información para resaltar los cambios en el texto y facilitar así el trabajo del operador.

4. Exportación a un formato externo

   También puede guardar el resultado de la comparación en formato XML y DOCX.

El procedimiento descrito a continuación también se ilustra con el ejemplo [Document Comparison](/es/fine-reader/engine/guided-tour/samples#documentcomparison_linux) para Linux y macOS, y con la herramienta de demostración para Windows [Document Comparison](/es/fine-reader/engine/guided-tour/samples#documentcomparison).

<div id="scenario-implementation">
  ## Implementación del escenario
</div>

<Note>
  Los ejemplos de código proporcionados en este tema son específicos de Windows.
</Note>

A continuación, se ofrece una descripción detallada del método recomendado para utilizar ABBYY FineReader Engine en este escenario.

<Accordion title="Paso 1. Carga de ABBYY FineReader Engine">
  Para empezar a trabajar con ABBYY FineReader Engine, debe crear el objeto [Engine](/es/fine-reader/engine/api-reference/engine-object-iengine-interface). El objeto Engine es el objeto superior en la jerarquía de objetos de ABBYY FineReader Engine y proporciona varias configuraciones globales, algunos métodos de procesamiento y métodos para crear los demás objetos.

  Para crear el objeto Engine, puede usar la función [InitializeEngine](/es/fine-reader/engine/api-reference/functions/initializeengine-function). Consulte también [otras formas de cargar el objeto Engine](/es/fine-reader/engine/guided-tour/advanced-techniques/programming-aspects/different-ways-to-load-engine) (Win).

  ### C\#

  ```csharp theme={null}
  public class EngineLoader : IDisposable
  {
      public EngineLoader()
      {
          // Inicialice estas variables con la ruta completa a FREngine.dll, su Customer Project ID,
          // y, si corresponde, la ruta al archivo de token de Online License y la contraseña de Online License
          string enginePath = "";
          string customerProjectId = "";
          string licensePath = "";
          string licensePassword = "";
          // Cargue la biblioteca FREngine.dll
          dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
             
          try
          {
              if (dllHandle == IntPtr.Zero)
              {
                  throw new Exception("Can't load " + enginePath);
              }
              IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
              if (initializeEnginePtr == IntPtr.Zero)
              {
                  throw new Exception("Can't find InitializeEngine function");
              }
              IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
              if (deinitializeEnginePtr == IntPtr.Zero)
              {
                  throw new Exception("Can't find DeinitializeEngine function");
              }
              IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
              if (dllCanUnloadNowPtr == IntPtr.Zero)
              {
                  throw new Exception("Can't find DllCanUnloadNow function");
              }
              // Convierta los punteros en delegados
              initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                  initializeEnginePtr, typeof(InitializeEngine));
              deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                  deinitializeEnginePtr, typeof(DeinitializeEngine));
              dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                  dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
              // Llame a la función InitializeEngine 
              // y pase la ruta al archivo de Online License y la contraseña de Online License
              int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                  "", "", false, ref engine);
              Marshal.ThrowExceptionForHR(hresult);
          }
          catch (Exception)
          {
              // Libere la biblioteca FREngine.dll
              engine = null;
              // Elimine todos los objetos antes de llamar a FreeLibrary
              GC.Collect();
              GC.WaitForPendingFinalizers();
              GC.Collect();
              FreeLibrary(dllHandle);
              dllHandle = IntPtr.Zero;
              initializeEngine = null;
              deinitializeEngine = null;
              dllCanUnloadNow = null;
              throw;
          }
      }
      // Funciones de 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);
      // Funciones de 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();
      // Variables privadas
      private FREngine.IEngine engine = null;
      // Identificador de FREngine.dll
      private IntPtr dllHandle = IntPtr.Zero;
      private InitializeEngine initializeEngine = null;
      private DeinitializeEngine deinitializeEngine = null;
      private DllCanUnloadNow dllCanUnloadNow = null;
  }
  ```
</Accordion>

<Accordion title="Paso 2. Carga y preprocesamiento de archivos e imágenes">
  ABBYY FineReader Engine proporciona el objeto [FRDocument](/es/fine-reader/engine/api-reference/document-related-objects/frdocument), que permite procesar documentos de varias páginas. El uso de este objeto le permite conservar la organización lógica del documento y mantener el texto original, así como las columnas, fuentes, estilos, etc. Use el objeto [FRPage](/es/fine-reader/engine/api-reference/document-related-objects/frpage) si desea comparar páginas.

  Para cargar imágenes de un solo documento y preprocesarlas, debe crear el objeto FRDocument y agregarle las imágenes. Puede hacerlo de una de las siguientes maneras:

  * Crear el objeto FRDocument mediante el método [CreateFRDocumentFromImage](/es/fine-reader/engine/api-reference/engine-object-iengine-interface/creation-methods/createfrdocumentfromimage-method) del objeto Engine. Este método crea el objeto FRDocument y carga las imágenes desde el archivo especificado.
  * Crear el objeto FRDocument mediante el método [CreateFRDocument](/es/fine-reader/engine/api-reference/engine-object-iengine-interface/creation-methods/createlessobjectgreater-methods) del objeto Engine y, a continuación, agregar imágenes desde un archivo al objeto FRDocument creado (use el método [AddImageFile](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/addimagefile-method), [AddImageFileWithPassword](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/addimagefilewithpassword-method) o [AddImageFileWithPasswordCallback](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/addimagefilewithpasswordcallback-method) del objeto FRDocument).

  ### C\#

  ```csharp theme={null}
  // Crear el objeto FRDocument a partir de un archivo de imagen
  FREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );
  ```
</Accordion>

<Accordion title="Paso 3. Reconocimiento de documentos">
  Para reconocer un documento, le recomendamos usar los métodos de análisis y reconocimiento del objeto FRDocument. Este objeto proporciona toda una serie de métodos para analizar, reconocer y sintetizar documentos. El método más práctico, que integra en una sola operación el análisis, el reconocimiento y la síntesis del documento, es [Process](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/process-method). Además, aprovecha de la forma más eficiente las funciones de procesamiento simultáneo de los sistemas multiprocesador y multinúcleo. No obstante, también puede realizar de forma secuencial el preprocesamiento, el análisis, el reconocimiento y la síntesis mediante los métodos [Preprocess](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/preprocess-method), [Analyze](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/analyze-method), [Recognize](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/recognize-method) y [Synthesize](/es/fine-reader/engine/api-reference/document-related-objects/frdocument/synthesize-method).<br />Puede establecer los parámetros de reconocimiento para sus documentos cargando un profile predefinido adecuado (consulte [Working with Profiles](/es/fine-reader/engine/guided-tour/advanced-techniques/working-with-profiles) para obtener más información).

  ### C\#

  ```csharp theme={null}
  // Procesar el documento con los parámetros predeterminados
  // Puede cambiarlos si es necesario; por ejemplo, cargando previamente un profile
  frDocument.Process( null );
  ```
</Accordion>

<Accordion title="Paso 4. Comparación de documentos o páginas">
  Para comparar los documentos o páginas con sus copias:

  1. Asegúrese de que su licencia de ABBYY FineReader Engine sea compatible con el módulo [Compare Documents](/es/fine-reader/engine/licensing/modules#comparedocuments).
  2. Cree un objeto [Comparator](/es/fine-reader/engine/api-reference/document-comparison-objects/comparator) mediante el método [CreateComparator](/es/fine-reader/engine/api-reference/engine-object-iengine-interface/creation-methods/createlessobjectgreater-methods) del objeto [Engine](/es/fine-reader/engine/api-reference/engine-object-iengine-interface).
  3. \[opcional] Use el objeto [ComparisonParams](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonparams) para configurar las propiedades con los valores que necesite.
  4. Llame al método [CompareDocuments](/es/fine-reader/engine/api-reference/document-comparison-objects/comparator/comparedocuments-method) del objeto [Comparator](/es/fine-reader/engine/api-reference/document-comparison-objects/comparator) para comparar el documento original con la copia. Recibirá un objeto [ComparisonResult](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonresult) que contiene información sobre los cambios detectados.

  ### C\#

  ```csharp theme={null}
  // Realizar la comparación de los documentos 
  FREngine.IComparator comparator = engine.CreateComparator();
  FREngine.IComparisonResult comparatorResult = 
      comparator.CompareDocuments( referenceFRDocument, userFRDocument, null, null );
  ```
</Accordion>

<Accordion title="Paso 5. Trabajo con los cambios detectados">
  El objeto [ComparisonResult](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonresult) contiene la lista completa de diferencias y proporciona métodos para obtener las diferencias de páginas concretas. Puede acceder a los cambios del documento original y de su copia con los métodos [GetChangesForReferencePage](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonresult/getchangesforreferencepage-method) y [GetChangesForUserPage](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonresult/getchangesforuserpage-method). Use el objeto [ChangeLocation](/es/fine-reader/engine/api-reference/document-comparison-objects/changelocation) para obtener información sobre la ubicación del cambio y su propiedad [RegionForPage](/es/fine-reader/engine/api-reference/document-comparison-objects/changelocation/regionforpage-property) para obtener la región del cambio en la página especificada.

  ### C\#

  ```csharp theme={null}
  // Obtener información sobre la modificación detectada y su ubicación en el documento original
  FREngine.IChanges changes = comparatorResult.Changes;
  foreach( FREngine.IChange change in changes ) {
        FREngine.ModificationTypeEnum modificationType = change.ModificationType;
        FREngine.IChangeLocation referenceLocation = change.ReferenceLocation;
        // Ahora puede resaltar estos cambios en la página para que un operador los revise
        ... 
  }
  ```
</Accordion>

<Accordion title="Paso 6. Exportación del resultado de la comparación">
  Para exportar el resultado de la comparación, llame al método [Export](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonresult/export-method) del objeto [ComparisonResult](/es/fine-reader/engine/api-reference/document-comparison-objects/comparisonresult) y pase la ruta del archivo como parámetro de entrada. Los datos pueden guardarse en XML o en un archivo DOCX con control de cambios.

  C#

  ```csharp theme={null}
  // Guardar en formato XML
  comparisonResult.Export( "C:\\ComparisonResult.xml", FREngine.ComparatorExportFormatEnum.CEF_Xml, null );
  ```
</Accordion>

<Accordion title="Paso 7. Descarga de ABBYY FineReader Engine">
  Después de terminar de trabajar con ABBYY FineReader Engine, debe descargar el objeto [Engine](/es/fine-reader/engine/api-reference/engine-object-iengine-interface). Para ello, use la función exportada [DeinitializeEngine](/es/fine-reader/engine/api-reference/functions/deinitializeengine-function).

  ### C\#

  ```csharp theme={null}
  public class EngineLoader : IDisposable
  {
      // Descargar FineReader Engine
      public void Dispose()
      {
          if (engine == null)
          {
              // El Engine no se cargó
              return;
          }
          engine = null;
          // Eliminar todos los objetos antes de llamar 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;
          // lanzar la excepción después de la limpieza
          Marshal.ThrowExceptionForHR(hresult);
      }
      // Funciones de 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);
      // Funciones de 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();
      // Variables privadas
      private FREngine.IEngine engine = null;
      // Handle de FREngine.dll
      private IntPtr dllHandle = IntPtr.Zero;
      private InitializeEngine initializeEngine = null;
      private DeinitializeEngine deinitializeEngine = null;
      private DllCanUnloadNow dllCanUnloadNow = null;
  }
  ```
</Accordion>

<div id="required-resources">
  ## Recursos necesarios
</div>

Puede usar el archivo [FREngineDistribution.csv](/es/fine-reader/engine/distribution/distribution-windows/distribution-kit/working-with-the-frenginedistributioncsv-file) para crear automáticamente una lista de los archivos necesarios para que su aplicación funcione. Para procesar con este escenario, seleccione en la columna 5 (RequiredByModule) los siguientes valores:

Core

Core.Resources

Opening

Opening, Processing

Processing

Processing.OCR

Processing.OCR, Processing.ICR

Processing.OCR.NaturalLanguages

Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages

Export

Export, Processing

Si modifica el escenario estándar, cambie los módulos necesarios en consecuencia. También debe especificar los idiomas de la interfaz, los idiomas de reconocimiento y cualquier función adicional que use su aplicación (como, por ejemplo, Opening.PDF si necesita abrir archivos PDF, o Processing.OCR.CJK si necesita reconocer textos en [idiomas CJK](/es/fine-reader/engine/guided-tour/advanced-techniques/recognizing-cjk-languages#cjk)). Consulte [Working with the FREngineDistribution.csv File](/es/fine-reader/engine/distribution/distribution-windows/distribution-kit/working-with-the-frenginedistributioncsv-file) para obtener más información.

<div id="additional-optimization-for-specific-tasks">
  ## Optimización adicional para tareas específicas
</div>

A continuación se ofrece una visión general de los temas de Ayuda que contienen información adicional sobre cómo personalizar la configuración en distintas etapas del procesamiento:

* Escaneo: solo para Windows
  * [Escaneo](/es/fine-reader/engine/guided-tour/basic-usage-scenarios-implementation/scanning)<br />Descripción del escenario de ABBYY FineReader Engine para el escaneo de documentos.
* Reconocimiento
  * [Ajuste de los parámetros de preprocesamiento, análisis, reconocimiento y síntesis](/es/fine-reader/engine/guided-tour/advanced-techniques/tuning-parameters-of-preprocessing-analysis-recognition-and-synthesis)<br />Personalización del procesamiento de documentos mediante objetos de parámetros de análisis, reconocimiento y síntesis.
  * [PageProcessingParams Object](/es/fine-reader/engine/api-reference/parameter-objects/preprocessing-analysis-recognition-and-synthesis-parameters/pageprocessingparams)<br />Este objeto permite personalizar los parámetros de análisis y reconocimiento. Con este objeto, puede indicar qué características de la imagen y del texto deben detectarse (imagen invertida, orientación, códigos de barras, idioma de reconocimiento, margen de error de reconocimiento).
  * [SynthesisParamsForPage Object](/es/fine-reader/engine/api-reference/parameter-objects/preprocessing-analysis-recognition-and-synthesis-parameters/synthesisparamsforpage)<br />Este objeto incluye parámetros responsables de restaurar el formato de una página durante la síntesis.
  * [SynthesisParamsForDocument Object](/es/fine-reader/engine/api-reference/parameter-objects/preprocessing-analysis-recognition-and-synthesis-parameters/synthesisparamsfordocument)<br />Este objeto permite personalizar la síntesis del documento: restaurar su estructura y formato.
  * [MultiProcessingParams Object](/es/fine-reader/engine/api-reference/parameter-objects/multiprocessingparams) - Implementado para Linux y Windows<br />El procesamiento simultáneo puede resultar útil al procesar una gran cantidad de imágenes. En este caso, la carga de procesamiento se distribuirá entre los núcleos del procesador durante la apertura y el preprocesamiento de las imágenes, el análisis del diseño, el reconocimiento y la exportación, lo que permite acelerar el procesamiento.<br />Los modos de lectura (simultáneo o consecutivo) se configuran mediante la propiedad MultiProcessingMode. La propiedad RecognitionProcessesCount controla la cantidad de procesos que pueden iniciarse.

<div id="see-also">
  ## Consulte también
</div>

[Implementación de escenarios de uso básicos](/es/fine-reader/engine/guided-tour/basic-usage-scenarios-implementation)
