Integración de OCR en el navegador con tesseract.js
El reconocimiento óptico de caracteres (OCR, por sus siglas en inglés) ha sido tradicionalmente una tarea del lado del servidor, que obligaba a los usuarios a subir documentos a un servidor para procesarlos. Sin embargo, con los avances en las tecnologías web, ahora es posible realizar el reconocimiento de texto directamente en el navegador. Este cambio hacia el OCR en el navegador ofrece respuesta inmediata, mayor privacidad y menor carga del servidor. En este artículo, exploraremos cómo integrar el OCR en tus aplicaciones web con la biblioteca de código abierto Tesseract.js, para reconocer texto al instante sin salir del navegador.
¿Por qué usar OCR en el navegador?
Ejecutar OCR en el navegador ofrece varias ventajas:
- Respuesta inmediata: los usuarios reciben resultados al instante, sin esperar el procesamiento en el servidor.
- Mayor privacidad: los documentos confidenciales nunca salen del dispositivo del usuario, lo que responde a las preocupaciones de privacidad.
- Menor carga del servidor: delegar el procesamiento en el cliente reduce los costos del servidor y el uso de recursos.
- Capacidades sin conexión: el OCR puede ejecutarse sin conexión después de que la aplicación, el script del worker, el núcleo WASM y los datos de idioma necesarios se hayan descargado y almacenado en caché para su uso sin conexión. El ejemplo con CDN que aparece abajo necesita conexión de red en su primera ejecución.
Presentamos tesseract.js: una potente biblioteca de OCR de código abierto
Tesseract.js es una biblioteca de JavaScript de código abierto que lleva las robustas capacidades del motor de OCR Tesseract de Google a las aplicaciones web. La versión 6.0.0 introduce mejoras importantes en la gestión de memoria, el rendimiento en tiempo de ejecución y la estabilidad general. Ahora la biblioteca se centra en la funcionalidad principal de reconocimiento de texto, con todos los formatos de salida excepto «text» desactivados de forma predeterminada para obtener un rendimiento óptimo.
Novedades de tesseract.js v6.0.0
Tesseract.js v6.0.0 llega con varias mejoras clave:
- Se corrigieron fugas de memoria para lograr sesiones prolongadas más estables.
- Menor tiempo de ejecución y uso de memoria para un reconocimiento de texto más rápido.
- Los formatos de salida distintos de «text» están desactivados de forma predeterminada para optimizar el rendimiento.
- Inicialización de la API simplificada para una integración más sencilla.
Compatibilidad y requisitos del navegador
Usa una versión actual de Chrome, Firefox, Safari o Edge con compatibilidad con WebAssembly (WASM) y Web Worker. La compatibilidad con WASM por sí sola no garantiza la compatibilidad con todas las dependencias de Tesseract.js.
Asegúrate de que tu servidor sirva correctamente los archivos WebAssembly con el tipo MIME «application/wasm».
Primeros pasos con tesseract.js
Instalación
Puedes añadir Tesseract.js a tu proyecto con npm:
npm install tesseract.js@6
O incluirlo mediante CDN:
<script src="https://unpkg.com/tesseract.js@v6.0.0/dist/tesseract.min.js"></script>
Tesseract.js carga automáticamente los archivos WASM necesarios. Asegúrate de que tu servidor admita los tipos MIME correctos para WASM.
Ejemplo básico: reconocer texto de una imagen
A continuación se muestra un ejemplo sencillo de cómo aplicar OCR a una imagen. Incluye el script del CDN anterior antes de este bloque. Tesseract.js acepta imágenes; convierte las páginas de PDF en imágenes con un renderizador de PDF aparte antes de pasarlas al OCR.
<input type="file" id="imageInput" accept="image/*" />
<div id="result"></div>
<script>
async function performOCR(file) {
const worker = await Tesseract.createWorker('eng', 1, {
logger: (msg) => console.log('Worker progress:', msg),
errorHandler: () => console.error('OCR worker failed.'),
})
try {
const {
data: { text },
} = await worker.recognize(file)
return text
} finally {
await worker.terminate()
}
}
document.getElementById('imageInput').addEventListener('change', async (e) => {
const file = e.target.files[0]
const resultElement = document.getElementById('result')
if (!file) return
if (!file.type.startsWith('image/')) {
resultElement.textContent = 'Please select an image file.'
return
}
resultElement.textContent = 'Processing…'
try {
const text = await performOCR(file)
resultElement.textContent = text
} catch {
resultElement.textContent = 'Unable to recognize this image. Please try another image.'
}
})
</script>
Manejo de varios idiomas
El errorHandler del worker gestiona su evento de error; un reconocimiento fallido
igualmente rechaza la promesa de recognize(), y finally
termina el worker inicializado.
Tesseract.js admite varios idiomas. Así puedes aplicar OCR a imágenes que contienen texto en varios idiomas:
async function performMultilingualOCR(file, languages = ['eng', 'deu']) {
const worker = await Tesseract.createWorker(languages, 1, {
logger: (msg) => console.log('Worker progress:', msg),
errorHandler: () => console.error('OCR worker failed.'),
})
try {
const {
data: { text },
} = await worker.recognize(file)
return text
} finally {
await worker.terminate()
}
}
Optimización del rendimiento
Puedes mejorar el rendimiento y la precisión del OCR con algunas técnicas adicionales.
Preprocesamiento de imágenes
Prueba filtros o cambios de tamaño en tus imágenes de entrada y compara la precisión del reconocimiento. Reducir la escala puede borrar el texto pequeño, así que el ancho que aparece abajo es un equilibrio con la memoria, no un ajuste universal de OCR:
async function preprocessImage(file) {
const url = URL.createObjectURL(file)
try {
const img = new Image()
await new Promise((resolve, reject) => {
img.onload = resolve
img.onerror = () => reject(new Error('Unable to decode image.'))
img.src = url
})
const canvas = document.createElement('canvas')
const maxWidth = 1000
const scale = img.width > maxWidth ? maxWidth / img.width : 1
canvas.width = Math.max(1, Math.round(img.width * scale))
canvas.height = Math.max(1, Math.round(img.height * scale))
const ctx = canvas.getContext('2d')
if (!ctx) throw new Error('Canvas processing is unavailable.')
ctx.filter = 'grayscale(100%) contrast(150%)'
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
return await new Promise((resolve, reject) => {
canvas.toBlob((blob) => {
if (blob) resolve(blob)
else reject(new Error('Unable to encode processed image.'))
}, 'image/png')
})
} finally {
URL.revokeObjectURL(url)
}
}
async function optimizedOCR(file) {
const processedImage = await preprocessImage(file)
return performOCR(processedImage)
}
Gestión de memoria
Gestionar de forma eficiente el ciclo de vida del worker es fundamental, sobre todo cuando procesas varias imágenes:
async function batchProcessImages(files) {
const worker = await Tesseract.createWorker('eng', 1, {
logger: (msg) => console.log('Worker progress:', msg),
errorHandler: () => console.error('OCR worker failed.'),
})
const results = []
try {
for (const file of files) {
const {
data: { text },
} = await worker.recognize(file)
results.push(text)
}
} finally {
await worker.terminate()
}
return results
}
Manejo de errores y validación
Un manejo de errores robusto es esencial para una experiencia de usuario fluida. El siguiente ejemplo añade la validación del tipo y el tamaño de archivo, junto con un reporte de errores adecuado:
async function validateAndPerformOCR(file) {
const MAX_SIZE = 5 * 1024 * 1024 // 5MB
const SUPPORTED_TYPES = ['image/jpeg', 'image/png', 'image/webp']
if (!SUPPORTED_TYPES.includes(file.type)) {
throw new Error('Unsupported file type. Please use JPEG, PNG, or WebP images.')
}
if (file.size > MAX_SIZE) {
throw new Error('File size exceeds 5MB limit.')
}
return performOCR(file)
}
Consideraciones de seguridad y buenas prácticas
Cuando implementes OCR en el navegador, ten en cuenta las siguientes pautas:
- Informar a los usuarios de que el procesamiento ocurre localmente para garantizar la privacidad de los datos.
- Validar los tipos y tamaños de archivo para evitar comportamientos inesperados.
- Supervisar el uso de memoria y liberar adecuadamente las instancias de worker.
- Considerar la carga progresiva de las imágenes grandes para no bloquear la interfaz.
- Ofrecer información clara y en tiempo real durante el procesamiento.
- Gestionar los errores con elegancia, mediante mensajes claros para el usuario.
Consulta la API de worker de Tesseract.js para conocer las opciones de inicialización, incluidas las rutas a los recursos de worker, núcleo e idioma alojados localmente.
Conclusión
Tesseract.js v6.0.0 ofrece una solución potente para implementar OCR directamente en navegadores web, con un rendimiento mejorado, una gestión de memoria robusta y una API simplificada. Si sigues las buenas prácticas descritas en esta guía, podrás crear aplicaciones de OCR eficientes, seguras y fáciles de usar, que respetan la privacidad de los usuarios y entregan resultados rápidos.
Si necesitas una solución de OCR más avanzada, con procesamiento del lado del servidor y compatibilidad con varios formatos de documento, echa un vistazo al servicio de OCR de documentos de Transloadit.
