Volver al feed
🇨🇱Chile·Laboral Skill· 23 abr 2026· ES

OCR inteligente: leer fotos, escaneos y PDFs para citar en escritos

Pipeline auto-decisor (texto nativo / OCR estándar / OCR foto con OpenCV) que entrega .txt trazables con confianza por página.

JM
José MuñozTop· @jose_munoz· Santiago
4.8(4)
2 comentarios65descargas Historial
skill.md · Laboral
---
name: lectura-inteligente-documentos
description: Extrae texto trazable y citable desde documentos heterogéneos (PDFs nativos o escaneados, fotos de celular, JPG/PNG/HEIC, DOCX, TXT) para usar en escritos judiciales laborales chilenos (demandas, contestaciones, réplicas, recursos). Decide sola el pipeline por página (texto nativo, OCR estándar, OCR foto con preprocesamiento OpenCV), mide confianza por página, detecta datos críticos (montos, fechas, RUTs, cláusulas). Usala cuando el usuario diga "extrae el texto", "OCR", "léeme esta liquidación/finiquito/contrato", "pásame a texto", "el cliente mandó fotos", "transcribe estos documentos", "procesa los papeles", "preparalos para citar", "documento fotografiado/escaneado", "léeme el PDF del expediente", o suba imágenes sueltas o carpetas con PDFs nativos y escaneados mezclados. Funciona aunque no mencione OCR — basta con pedir leer, transcribir o usar documentos que no están en texto plano.
---

# Lectura inteligente de documentos

## Autonomía y foco

Esta skill **funciona sola**. No depende de ninguna otra skill para ejecutarse. El insumo son los archivos que el usuario pone en el workspace (fotos del celular, escaneos, DOCX, PDFs, imágenes sueltas) — no presupone que vengan de un pipeline upstream.

**Foco real**: documentos que el *cliente* o la contraparte le manda al abogado y que llegan en cualquier formato (fotos de WhatsApp, escaneos de la multifuncional, papeles fotografiados sobre la mesa). Eso es lo que rutinariamente requiere OCR.

**No es para ebooks del PJUD ni piezas de expediente completas** — esas normalmente vienen como PDFs nativos con capa de texto y no necesitan OCR. Si el usuario pide procesar un "ebook" o un "expediente" descargado directamente del sistema judicial, probablemente pdfplumber basta y la skill actuará rápido en modo texto nativo; pero no es el caso de uso principal al que apunta.

### Otras skills que pueden aparecer alrededor (opcionales, no requeridas)

La skill produce archivos planos (`.txt`, `.meta.json`, PNGs) que cualquier otra skill o tool puede consumir después, sin que tengan que conocerse entre sí. Ejemplos de combinaciones útiles (pero todas opcionales):

- Si el usuario quiere el texto consolidado como `.docx` con formato, puede usar luego la skill `docx` por separado.
- Si quiere una matriz de datos extraídos (montos, fechas, RUTs por documento) como spreadsheet, el `.meta.json` alimenta bien a la skill `xlsx`.
- Si recibe los documentos mal orientados o mezclados en un solo PDF, la skill `pdf` puede preprocesarlos antes.

Ninguna de estas es precondición para que `lectura-inteligente-documentos` funcione — si no están instaladas, no pasa nada.

## Programas y librerías necesarios

La skill no funciona sin estas dependencias. El script `scripts/verificar_deps.py` las detecta e informa cuáles faltan. Si estás en un sandbox fresco, instalalas **antes** de llamar a `main.py`.

### Binarios del sistema (apt / brew)

| Programa | Para qué sirve | Paquete Debian/Ubuntu | Obligatoriedad |
|---|---|---|---|
| `tesseract` | OCR fallback (siempre presente como red de seguridad) | `tesseract-ocr` + `tesseract-ocr-spa` | **Obligatorio** |
| `poppler-utils` (`pdftoppm`, `pdfinfo`) | Rasterizar PDFs a PNG y leer metadata | `poppler-utils` | **Obligatorio** |
| `ghostscript` | Requerido por `ocrmypdf` para optimización PDF | `ghostscript` | **Obligatorio** |
| `heif-convert` | Convertir fotos HEIC del iPhone a JPG | `libheif-examples` | Recomendado |
| `unpaper` | Limpieza opcional previa al OCR | `unpaper` | Opcional |

### Librerías Python (pip install --break-system-packages)

| Librería | Para qué la usa la skill | Obligatoriedad |
|---|---|---|
| `pdfplumber` | Detectar capa de texto y extraer texto nativo de PDFs | **Obligatorio** |
| `pypdf` | Metadata y conteo de páginas | **Obligatorio** |
| `ocrmypdf` | OCR sobre PDFs escaneados limpios (wrapper sobre tesseract) | **Obligatorio** |
| `opencv-python-headless` | Preprocesamiento de fotos (bordes, perspectiva, CLAHE, denoising) | **Obligatorio** |
| `pytesseract` | Wrapper Python para Tesseract (páginas sueltas) | **Obligatorio** |
| `python-docx` | Lectura de archivos DOCX | **Obligatorio** |
| `Pillow` | Apertura/escritura de imágenes | **Obligatorio** |
| `pdf2image` | Rasterizado de PDFs a PIL.Image | **Obligatorio** |
| `numpy` | Operaciones matriciales usadas por OpenCV | **Obligatorio** |
| `pillow-heif` | Soporte nativo HEIC en Pillow | Recomendado |
| `paddleocr` + `paddlepaddle` | OCR primario de alta precisión para fotos (modelo español) | Opcional — si no está, Tesseract cubre |

Si `paddleocr` no está disponible, la skill degrada automáticamente a Tesseract. No rompas el flujo por eso.

### MCPs / herramientas externas (no se instalan, pero se asumen)

- **Chrome MCP** — sólo si el input todavía no existe y hay que descargarlo primero vía `ojv-recopilador`. Esta skill no lo invoca directamente; lo hace la skill upstream.
- **Tool multimodal de lectura de imágenes de Claude** — fallback final cuando el OCR no da. La skill deja los PNG problemáticos listos en `paginas_revision/` y Claude los lee con su capacidad multimodal nativa.

## Para qué sirve esta skill

El usuario es abogado laboralista en Chile. Recibe de sus clientes documentos en cualquier condición: fotos tomadas con el celular sobre la mesa de la cocina, escaneos en 300 dpi de la multifuncional del trabajo, PDFs bajados del PJUD, DOCX exportados desde la Oficina Judicial Virtual, capturas de WhatsApp, etc. Todo eso termina citado en un escrito judicial. El problema: si el OCR está mal, el escrito cita un monto o una fecha equivocada y se desmorona la defensa.

Esta skill transforma ese caos en **archivos `.txt` estructurados con metadatos de confianza por página**, para que el agente redactor sepa qué puede citar textualmente y qué tiene que verificar a ojo antes de pegarlo en la demanda.

El entregable **NO** es un PDF con capa OCR. Es texto plano trazable: cada página del documento original queda representada en el .txt con un indicador de qué método se usó, qué confianza tiene, y qué datos críticos (montos, fechas, RUTs) aparecen en esa página.

## Principio operativo: auto-decisión

La skill **no le pregunta al usuario qué modo usar**. Decide sola. El usuario ya tiene suficientes decisiones que tomar. Si la skill pregunta "¿modo rápido o exhaustivo?", ya falló.

El orquestador (`main.py`) hace lo siguiente:

1. Llama a `triage.py` para clasificar los archivos de entrada.
2. Decide el modo (rápido / autónomo / autónomo con progreso) a partir del conteo y tamaño.
3. Decide el pipeline por página (texto nativo / OCR estándar / OCR foto).
4. Ejecuta, scorea, hace bucle de mejora donde haga falta.
5. Genera `.txt`, `.meta.json`, `/paginas_revision/`, y un reporte final en chat.

## Cuándo usar esta skill — contextos gatillantes

Cualquier pedido del usuario que implique "convertir documentos en texto utilizable" cae acá. Algunos ejemplos reales:

- "El cliente me acaba de mandar 12 fotos de su contrato y el finiquito, dame el texto"
- "Tengo este PDF escaneado de una carta de despido, sácame el texto limpio"
- "Acá hay 40 páginas del expediente, léelas y prepáralas para que pueda citar"
- "Pásame la liquidación a texto para ver si el cálculo está bien"
- "Hazle OCR a esto y dime si los datos quedan bien"
- "Procesa estos papeles para la contestación"

Si el usuario sube archivos y menciona "contestación", "demanda", "escrito", "expediente", "carpeta" o nombres de documentos laborales típicos (liquidación, finiquito, contrato, carta de despido, amonestación, licencia médica, comprobante de cotizaciones), **asume que esta skill aplica** salvo que el usuario diga explícitamente otra cosa.

## Flujo de trabajo

Lee este archivo por completo, luego ejecuta `main.py` apuntándolo a la carpeta o archivos que el usuario subió. El script se encarga de todo el resto.

### 1. Onboarding de dependencias (SÓLO al primer uso)

El primer paso de la skill es siempre correr `verificar_deps.py --json`. Esto no es "nice to have" — si falta una dependencia obligatoria, `main.py` va a generar un reporte vacío o confuso, y lo que el usuario va a ver es una skill rota sin saber por qué.

```bash
python /sessions/elegant-admiring-galileo/mnt/.claude/skills/lectura-inteligente-documentos/scripts/verificar_deps.py --json
```

El `--json` te devuelve una estructura con:

- `todo_ok`: bool — si está en `true`, seguí directo al paso 2.
- `faltantes_obligatorios`: qué componentes obligatorios faltan.
- `comandos_instalacion`: comandos listos para pegar en la terminal del usuario, adaptados a su plataforma (Linux/macOS/Windows).

#### Si `todo_ok = true`

Seguí al paso 2 sin decirle nada al usuario sobre dependencias. Él no necesita saber que verificaste — es ruido.

#### Si `todo_ok = false` (primer uso, componentes faltantes)

**No ejecutes `main.py`.** Primero detené el flujo y conducí al usuario por la instalación. La guía acá tiene un *porqué*: el usuario probablemente es abogado, no desarrollador, y un mensaje de error críptico lo va a frustrar. Mejor un onboarding corto y claro.

**Respondé al usuario con esta estructura** (adaptá el lenguaje — esto es una guía, no una plantilla rígida):

1. **Contale que faltan componentes** con una frase corta y humana. Ejemplo:

   > Antes de procesar los documentos, necesito instalar un par de cosas en tu computadora — es una sola vez. Son herramientas que sirven para leer texto desde imágenes y PDFs escaneados.

2. **Listá lo que falta** usando las descripciones del JSON, no los nombres técnicos. Si falta `tesseract-ocr-spa`, no digas "tesseract-ocr-spa" — decí "el paquete de idioma español para el motor de OCR (si no está, se usa inglés y los documentos en español salen con errores)". El JSON te da el campo `descripcion` exactamente con esta intención.

3. **Dale los comandos listos para pegar**, en un bloque de código, exactamente como vienen en `comandos_instalacion.obligatorios`. Si la plataforma detectada es Linux pero el usuario parece estar en macOS, ofrecé también los comandos equivalentes de `brew` (podés correr `verificar_deps.py` con el entorno correcto o armar el comando de cabeza desde los campos `paquete_brew` del JSON).

4. **Explicá qué hace cada bloque** en una línea. Ejemplo:

   > Copiá y pegá esto en tu terminal. El primer comando instala los motores de OCR y utilidades de PDF; el segundo instala las librerías de Python que uso para procesar imágenes.

5. **Ofrecé los opcionales por separado**, aclarando que no son obligatorios:

   > Si además querés la mejor calidad posible en fotos de celular, podés instalar estos extras (no son obligatorios):
   > ```
   > pip install paddleocr paddlepaddle
   > ```
   > La diferencia: sin esto uso Tesseract, que funciona bien con escaneos; con esto uso PaddleOCR, que es mejor con fotos torcidas o mal iluminadas.

6. **Si la plataforma es Windows**, no pretendas que todo funciona: Tesseract en Windows nativo requiere un instalador (UB Mannheim). Sugerí WSL como alternativa más simple, que es lo que hace el propio `verificar_deps.py`.

7. **Cerrá pidiendo que te avise cuando haya terminado**, o si prefiere que vos corras los comandos por él en la terminal integrada (si tiene permisos de Cowork Computer Use). Ejemplo:

   > Avisame cuando lo hayas instalado y proceso los documentos. O, si preferís, puedo correr los comandos yo mismo en tu terminal — confirmame y avanzo.

**Importante**: NO ejecutes la instalación sin permiso explícito del usuario. Instalar cosas en la computadora de un abogado sin avisarle es invasivo aunque tengas la capacidad técnica. Esperá el OK.

**Después de que el usuario diga "listo"**, volvé a correr `verificar_deps.py --json` para confirmar. Si sigue faltando algo, mostrale qué quedó pendiente y el comando específico para esa pieza — probablemente es el paquete de idioma español que se olvida porque se instala aparte de `tesseract`. Recién cuando `todo_ok = true`, proceder al paso 2.

### 2. Ejecutar la skill

```bash
python /sessions/elegant-admiring-galileo/mnt/.claude/skills/lectura-inteligente-documentos/scripts/main.py \
    --input "/sessions/elegant-admiring-galileo/mnt/uploads" \
    --output "/sessions/elegant-admiring-galileo/mnt/outputs"
```

`--input` puede ser un archivo, varios archivos separados por coma, o una carpeta. La skill detecta extensiones válidas (pdf, docx, txt, jpg, jpeg, png, heic, heif, webp, tif, tiff, bmp) e ignora el resto.

#### Flags de control para lotes grandes

Cuando el usuario sube una carpeta con muchos documentos (típico al procesar un expediente entero), `main.py` soporta cinco flags adicionales pensados para procesamiento masivo:

| Flag | Default | Para qué sirve |
|---|---|---|
| `--workers N` | `2` | Cantidad de archivos procesados en paralelo (vía `ProcessPoolExecutor`). Subilo a 4 si la máquina tiene CPU libre; bajalo a `1` para correr serial (útil al depurar). |
| `--rehacer` | off | Ignora el checkpoint y reprocesa todos los archivos aunque ya estén cacheados. Usalo cuando el usuario quiere re-analizar un lote que cambió o cuando cambiaste de versión de engine. |
| `--auto-confirmar` | off | Saltea la pantalla de preview aunque el lote exceda los umbrales (ver sección 2a abajo). |
| `--max-paginas N` | `100` | Umbral para disparar el preview. Si el triage estima más páginas que esto y no hay `--auto-confirmar`, la skill corta antes de procesar. |
| `--max-bytes-mb N` | `200` | Mismo umbral, medido en tamaño total del lote. |

**Checkpoint automático**: `main.py` siempre deja un `.lectura-progreso.json` en el `--output`. La próxima corrida sobre la misma carpeta reutiliza los resultados cacheados (verificando que los `.txt` de salida sigan existiendo). Si el usuario quiere forzar un reproceso, usá `--rehacer`.

**Reporte compacto**: cuando el lote tiene más de 10 archivos, el reporte completo (con `paginas_detalle` de cada documento) se escribe a `{output}/reporte.json` en disco, y el stdout sólo imprime una versión resumida con las top 20 páginas críticas. Esto evita inundar la ventana de contexto al presentar el reporte al usuario.

#### 2a. Preview en lotes grandes (código de salida 2)

Antes de correr el pipeline pesado, el orquestador evalúa si el lote excede los umbrales (`--max-paginas` o `--max-bytes-mb`). Si los excede y el usuario no puso `--auto-confirmar`, `main.py` imprime en stdout un JSON con status `"preview"` y **sale con código 2**. No procesa nada.

El JSON de preview incluye:

```json
{
  "status": "preview",
  "mensaje": "...",
  "total_archivos": N,
  "total_paginas": N,
  "total_mb": N,
  "tiempo_estimado_seg": N,
  "modo_propuesto": "rapido|autonomo|autonomo_progreso",
  "alta_precision": bool,
  "archivos": [
    {"nombre": "...", "tipo": "pdf", "paginas": N, "size_mb": N,
     "perfil_principal": "foto_celular|escaneo_limpio|texto_nativo",
     "palabras_clave": ["finiquito", ...]},
    ...
  ]
}
```

**Cómo tratar el exit code 2**: al detectarlo, presentá al usuario el resumen en prosa (cantidad de archivos, páginas, tiempo estimado, tipos detectados) y preguntale si quiere proceder. Si dice que sí, re-invocá `main.py` exactamente igual pero agregando `--auto-confirmar`. Si quiere filtrar, pedíle que achique la selección y re-corré.

Plantilla sugerida para la confirmación en chat:

```
### Previo a procesar — confirmación

Detecté **N archivo(s)** con un total de **N páginas** (~N MB), y el procesamiento estimado toma ~Xs en modo {modo_propuesto}{", alta precisión activada" si alta_precision}.

Tipos detectados:
- Fotos de celular: N archivo(s)
- Escaneos limpios: N archivo(s)
- PDFs con texto nativo: N archivo(s)

Documentos con palabras críticas detectadas:
- `archivo.pdf` — finiquito, contrato de trabajo
- ...

¿Proceso el lote completo o querés filtrar antes?
```

### 3. Entregar el reporte al usuario

Cuando `main.py` termina, imprime un JSON en stdout con el reporte estructurado. Ese JSON tiene todo lo necesario para construir la respuesta en chat:

```json
{
  "archivos": [...],
  "tiempo_total_seg": 47.3,
  "confianza_global": 91,
  "clasificacion_paginas": {"alta": 34, "media": 8, "baja": 2},
  "paginas_criticas": [...],
  "rutas_salida": {...},
  "recomendacion": "Utilizable, verificar citas de páginas marcadas"
}
```

Formatea ese JSON en la respuesta final al usuario siguiendo la plantilla de la sección "Reporte final en chat" más abajo. No simplemente vuelques el JSON — el usuario quiere leer un reporte en prosa con barra visual de confianza y listado claro de páginas a revisar.

## Cómo decide el modo de operación

`triage.py` muestrea 3 páginas aleatorias de cada documento y clasifica cada página como:

- `texto_nativo` — tiene capa de texto extraíble con pdfplumber (>50 caracteres útiles por página)
- `escaneo_limpio` — imagen de documento con bordes rectos, alto contraste, iluminación uniforme
- `foto_celular` — iluminación desigual, perspectiva torcida, fondo visible, borrosidad

A partir de eso decide:

- **≤5 páginas**: modo rápido, reporte inline inmediato
- **6–50 páginas**: modo autónomo, reporte completo al final
- **>50 páginas o >50 MB**: modo autónomo con log de progreso cada 10 páginas
- **Palabras clave detectadas** (`finiquito`, `liquidación`, `carta de despido`, `contrato de trabajo`, `acta de comparecencia`, `avenimiento`): activa **modo alta precisión** con doble pasada sobre páginas de confianza media

Estas reglas están implementadas en `scripts/triage.py`; no las dupliques acá.

## Pipeline de extracción por página

La regla general: **elige el pipeline más barato que te dé ≥90% de confianza**. No hagas OCR si hay capa de texto nativa. No uses preprocesamiento agresivo si el escaneo es limpio.

El orquestador decide el pipeline en este orden:

1. **DOCX / TXT** → `pipelines/texto_nativo.py` — lectura directa, sin OCR
2. **PDF con capa de texto válida** → `pipelines/texto_nativo.py` con pdfplumber
3. **PDF escaneado limpio** → `pipelines/ocr_estandar.py` con `ocrmypdf --language spa --deskew --sidecar`
4. **PDF con fotos embebidas / JPG / PNG / HEIC crudas** → `pipelines/ocr_fotos.py`:
   - Preprocesamiento OpenCV: detección de bordes, corrección de perspectiva (warp a rectángulo), CLAHE para normalizar iluminación, denoising, deskew fino
   - OCR con PaddleOCR (modelo español) si está disponible, fallback a Tesseract `--psm 6 -l spa`
5. **Documentos mixtos** (típico del PJUD: expediente con piezas nativas + escaneos) → procesamiento página por página, cada una con el pipeline óptimo

### Bucle de mejora

Si la confianza global del documento queda entre 70% y 85%, el orquestador dispara una **segunda pasada** sobre las páginas de baja confianza con:

- Rasterizado a 600 dpi (en vez de 300)
- Preprocesamiento más agresivo
- Cambio de engine (si la primera fue Tesseract, probar PaddleOCR, y viceversa)

Si la segunda pasada mejora el score, se incorpora. Si no, se reporta el límite honestamente — **no se fantasea con la confianza**. Un OCR malo reportado como malo es mucho más útil que un OCR malo reportado como bueno.

## Control de calidad y datos críticos

Cada página recibe un score de confianza 0–100%:
- **Texto nativo**: 100% (es lectura directa)
- **OCR**: promedio de confianza por palabra reportado por el engine

Clasificación:
- **Alta** (>90%) — uso directo recomendado
- **Media** (70–90%) — revisar citas textuales antes de pegar en el escrito
- **Baja** (<70%) — requiere revisión manual

---

_[Contenido truncado por el límite de tamaño de la plataforma. La skill original incluye además detalles del pipeline OCR (preprocesamiento OpenCV, doble pasada en alta precisión), formato del reporte final, manejo del checkpoint y plantilla del reporte en chat. Pídeme la versión completa por DM.]_
Tags:#ocr#tesseract#opencv#liquidación#finiquito

Califica este prompt

Promedio 4.8 con 4 votos.

Inicia sesión para calificar
Comentarios(2)
Inicia sesión para dejar tu comentario.

Relacionados en Laboral / Chile

Recibe los mejores prompts legales de la semana

Una selección curada por Skillex. Sin spam, cancelas cuando quieras.