feat: Agregar soporte OCR con Tesseract para PDFs escaneados

- Integrar Tesseract OCR para leer PDFs escaneados automáticamente
- Detectar automáticamente si el PDF tiene texto o requiere OCR
- Agregar servicio ocr_service.py con funciones de OCR
- Actualizar Dockerfile con tesseract-ocr, tesseract-ocr-spa y poppler-utils
- Agregar variables de configuración OCR (OCR_ENABLED, OCR_LANGUAGE, OCR_DPI, OCR_TIMEOUT)
- Crear endpoint de debug para ver texto extraído (/api/v1/debug/extract-text)
- Agregar scripts de instalación y prueba (install_ocr.ps1, test_ocr.py, debug_pdf.ps1)
- Documentación completa (OCR_SETUP.md, DOCKER_OCR.md, COMO_PROBAR.md)
- Actualizar docker-compose.yml con variables de entorno OCR
- Modificar pdf_text.py para usar OCR cuando sea necesario
- Actualizar requirements.txt con pytesseract, Pillow, pdf2image
This commit is contained in:
Ernesto Herrera
2026-03-04 08:21:41 -07:00
parent 068d859f42
commit fcc516c9b3
18 changed files with 1694 additions and 14 deletions

174
debug_pdf.ps1 Normal file
View File

@@ -0,0 +1,174 @@
# Script para ver qué texto extrajo el OCR de un PDF
# Uso: .\debug_pdf.ps1 -PdfPath "C:\ruta\al\archivo.pdf"
param(
[Parameter(Mandatory=$false)]
[string]$PdfPath,
[Parameter(Mandatory=$false)]
[string]$Token
)
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Debug: Ver texto extraído del PDF" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
# Si no se proporciona el path del PDF, preguntar
if (-not $PdfPath) {
$PdfPath = Read-Host "Ingresa la ruta completa del PDF"
}
# Verificar que el archivo existe
if (-not (Test-Path $PdfPath)) {
Write-Host "❌ Error: El archivo no existe: $PdfPath" -ForegroundColor Red
exit 1
}
Write-Host "📄 PDF: $PdfPath" -ForegroundColor White
$fileInfo = Get-Item $PdfPath
Write-Host "📊 Tamaño: $([math]::Round($fileInfo.Length / 1MB, 2)) MB" -ForegroundColor Gray
Write-Host ""
# Obtener token si no se proporcionó
if (-not $Token) {
Write-Host "🔑 Obteniendo token de autenticación..." -ForegroundColor Yellow
$body = @{
username = "admin"
password = "12345"
}
try {
$loginResponse = Invoke-RestMethod -Uri "http://localhost:9876/api/auth/login" `
-Method Post `
-ContentType "application/x-www-form-urlencoded" `
-Body $body
$Token = $loginResponse.access_token
Write-Host "✅ Token obtenido" -ForegroundColor Green
} catch {
Write-Host "❌ Error al obtener token: $_" -ForegroundColor Red
exit 1
}
}
Write-Host ""
Write-Host "🔍 Extrayendo texto del PDF..." -ForegroundColor Yellow
# Preparar la petición
$headers = @{
"Authorization" = "Bearer $Token"
}
$fileName = Split-Path $PdfPath -Leaf
$fileBytes = [System.IO.File]::ReadAllBytes($PdfPath)
# Crear form data
$boundary = [System.Guid]::NewGuid().ToString()
$LF = "`r`n"
$bodyLines = @(
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"$fileName`"",
"Content-Type: application/pdf$LF",
[System.Text.Encoding]::GetEncoding("iso-8859-1").GetString($fileBytes),
"--$boundary--$LF"
) -join $LF
try {
$response = Invoke-RestMethod -Uri "http://localhost:9876/api/v1/debug/extract-text" `
-Method Post `
-Headers $headers `
-ContentType "multipart/form-data; boundary=$boundary" `
-Body $bodyLines
Write-Host ""
Write-Host "============================================" -ForegroundColor Green
Write-Host " RESULTADO DE LA EXTRACCIÓN" -ForegroundColor Green
Write-Host "============================================" -ForegroundColor Green
Write-Host ""
# Información de extracción
Write-Host "📊 Estadísticas:" -ForegroundColor Cyan
Write-Host " • Método usado: $($response.extraction_info.method)" -ForegroundColor White
if ($response.extraction_info.method -eq "ocr") {
Write-Host " └─ ✅ SE USÓ OCR" -ForegroundColor Green
} else {
Write-Host " └─ No se usó OCR (el PDF tiene texto)" -ForegroundColor Yellow
}
Write-Host " • Páginas: $($response.extraction_info.pages)" -ForegroundColor White
Write-Host " • Caracteres: $($response.extraction_info.total_characters)" -ForegroundColor White
Write-Host " • Palabras: $($response.extraction_info.total_words)" -ForegroundColor White
Write-Host " • Líneas: $($response.extraction_info.total_lines)" -ForegroundColor White
Write-Host ""
# Configuración OCR
Write-Host "⚙️ Configuración OCR:" -ForegroundColor Cyan
Write-Host " • Habilitado: $($response.ocr_settings.ocr_enabled)" -ForegroundColor White
Write-Host " • Idioma: $($response.ocr_settings.ocr_language)" -ForegroundColor White
Write-Host " • DPI: $($response.ocr_settings.ocr_dpi)" -ForegroundColor White
Write-Host ""
# Texto extraído
Write-Host "📝 TEXTO COMPLETO EXTRAÍDO:" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Gray
Write-Host $response.full_text -ForegroundColor White
Write-Host "============================================" -ForegroundColor Gray
Write-Host ""
# Guardar en archivo
$outputFile = "$($PdfPath)_extracted_text.txt"
$response.full_text | Out-File -FilePath $outputFile -Encoding UTF8
Write-Host "💾 Texto guardado en: $outputFile" -ForegroundColor Green
Write-Host ""
# Análisis
if ($response.extraction_info.total_characters -lt 100) {
Write-Host "⚠️ ADVERTENCIA: Se extrajeron pocos caracteres ($($response.extraction_info.total_characters))" -ForegroundColor Yellow
Write-Host ""
Write-Host "Posibles causas:" -ForegroundColor Yellow
Write-Host " 1. El PDF está en blanco o casi vacío" -ForegroundColor White
Write-Host " 2. La calidad de la imagen es muy mala" -ForegroundColor White
Write-Host " 3. El texto es muy pequeño (intenta aumentar OCR_DPI a 600)" -ForegroundColor White
Write-Host " 4. La imagen tiene bajo contraste" -ForegroundColor White
Write-Host " 5. El texto no está en español (cambia OCR_LANGUAGE)" -ForegroundColor White
Write-Host ""
Write-Host "💡 Soluciones sugeridas:" -ForegroundColor Cyan
Write-Host " • Aumentar DPI: Edita .env y cambia OCR_DPI=600" -ForegroundColor White
Write-Host " • Cambiar idioma: Edita .env y cambia OCR_LANGUAGE=eng" -ForegroundColor White
Write-Host " • Mejorar calidad: Escanea el documento a mayor resolución" -ForegroundColor White
Write-Host ""
}
# Buscar palabras clave de incrementables
$keywords = @("incrementables", "fletes", "seguros", "almacenaje", "regalias", "ajuste")
$foundKeywords = @()
foreach ($keyword in $keywords) {
if ($response.full_text -match $keyword) {
$foundKeywords += $keyword
}
}
if ($foundKeywords.Count -gt 0) {
Write-Host "✅ Palabras clave encontradas: $($foundKeywords -join ', ')" -ForegroundColor Green
} else {
Write-Host "❌ No se encontraron palabras clave de incrementables" -ForegroundColor Red
Write-Host " El documento puede no contener información de incrementables" -ForegroundColor Yellow
}
Write-Host ""
} catch {
Write-Host ""
Write-Host "❌ Error al procesar el PDF:" -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
Write-Host ""
if ($_.Exception.Message -match "401") {
Write-Host "💡 El token expiró o es inválido. Intenta de nuevo." -ForegroundColor Yellow
}
}
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""