Todos los artículos

Cómo NavTorá sabe en qué columna está abierto el sefer

Seguimos paso a paso una foto real de un sefer, desde que la app separa la tinta del pergamino hasta que ubica la columna entre las 80.316 palabras de la Torá.

Es viernes y hay que dejar el sefer listo para Shabat. Quedó abierto en Masei, al final de Bamidbar, y mañana se lee desde Devarim 1:1. NavTorá resuelve justamente eso. Con una foto de la columna abierta, te dice dónde está el sefer, cuántas columnas hay que enrollar y para qué lado.

Para ubicarse, la app lee la columna (con errores y todo) y busca esas palabras entre las 80.316 de la Torá. No necesita tener guardado cómo se ve cada columna, así que sirve para cualquier sefer. La foto de este artículo es un cuadro real de una de las pruebas que grabamos, y lo que está dibujado encima sale de correr el código de la app sobre ella.

Un cuadro de una prueba real, en Masei, columna 198 del formato estándar.

Paso 1La foto

La foto es un cuadro de la grabación de pantalla de una de nuestras pruebas, recortado a lo que mostraba la cámara (le borramos la guía amarilla de la app). Tiene 480 por 688 píxeles, más o menos la cuarta parte de la resolución con la que la app saca las fotos. El pergamino está amarillento y tiene manchas, la columna se ve más angosta arriba que abajo porque el teléfono no estaba paralelo al sefer, y los renglones se curvan un poco porque el pergamino no está plano. A los costados, además, se ven partes de las columnas vecinas.

En la app, todo lo que sigue hasta tener el texto leído pasa en el teléfono, y la foto no se manda a ningún lado.

⇆
FotoTinta
Arrastrá la línea para comparar la foto con el mapa de tinta.

Paso 2Separar la tinta del pergamino

Lo primero que hace la app es sacarle a la foto el efecto de la luz. El brillo del pergamino cambia despacio a lo largo de la foto (una sombra de un lado, una lámpara del otro, una mancha), mientras que la tinta cambia de golpe, de un píxel al siguiente.

Para separarlas, la app hace una copia chiquita de la foto, de 160 píxeles de lado. En esa copia, cada punto toma el valor más claro de sus vecinos. Como las letras son finitas, desaparecen, y queda solo el fondo. Después, la app divide la foto por ese fondo. Es decir, donde hay pergamino el resultado queda blanco y donde hay tinta queda oscuro, esté a la sombra o al sol.

Si arrastrás la línea sobre la foto, vas a ver que las manchas y el amarillo desaparecen y las letras quedan.

En amarillo, los bordes de la columna. Abajo, la tinta sumada de arriba a abajo, con los márgenes como huecos.

Paso 3Encontrar la columna

En la foto se ven partes de tres columnas, y la que nos interesa es la del medio. Para encontrarla, la app suma la tinta de arriba a abajo en cada posición horizontal. Esa suma está dibujada abajo de la foto. Donde hay texto es alta, y en los márgenes en blanco que separan las columnas es casi cero.

La columna es el tramo con texto que contiene el centro de la foto, entre dos de esos huecos. Como el teléfono puede estar torcido, antes de sumar la app prueba inclinar la suma unos grados para cada lado y se queda con el ángulo que deja los bordes más nítidos. También mide los bordes en varias franjas de altura por separado (en esta foto, 5), para que sigan la perspectiva. La columna mide 265 píxeles de ancho arriba y 317 abajo.

A los costados, en verde, la tinta sumada fila por fila en la primera y la última tira (un pico por renglón). En amarillo, el camino de cada renglón.

Paso 4Seguir cada renglón

En un sefer, los renglones se apoyan en el sirtut, las rayas que el sofer marca antes de escribir. Por eso son paralelos y están a la misma distancia, y la app aprovecha eso.

Primero mide esa distancia. Corta la columna en seis tiras angostas, suma la tinta fila por fila en cada una y busca cada cuántos píxeles se repite el patrón. En esta foto, los renglones están cada 20,2 píxeles.

Después corta la columna en tiras más anchas (en esta foto, 3). En cada una, la suma fila por fila da un pico por renglón (a los costados de la foto están esas sumas para la primera y la última tira). Si el teléfono está torcido o el pergamino se curva, los picos de una tira no caen a la misma altura que los de la tira de al lado. Comparando tiras vecinas, la app mide cuánto sube o baja cada renglón de una a otra y con eso arma el camino de cada uno. En esta foto encontró 28 renglones.

La franja que se recorta alrededor de cada renglón.

Paso 5Recortar y enderezar

Cada renglón se recorta siguiendo su camino, como si se estirara el pergamino con los dedos, y queda en una tira de 32 píxeles de alto. Así, las curvas desaparecen.

Además, la tira se da vuelta como en un espejo. ¿Por qué? Porque la red que lee recorre la tira de izquierda a derecha, y el hebreo se escribe de derecha a izquierda. Dada vuelta, la primera letra del renglón queda primera y el texto sale en orden.

Como la recibe la red

Dada vuelta, como la leemos

Los primeros seis renglones de la foto, recortados por la app. A la izquierda están tal como los recibe la red, y a la derecha, dados vuelta para leerlos nosotros.
Lo que leyó la red en cada renglón. En naranja, las letras que no pudo leer.

Paso 6Leer letra por letra

Para leer, la app usa una red neuronal chica, de 1,8 MB, que corre en el teléfono (la primera versión leía con Claude, y lo cuento en otro artículo). Unas capas convolucionales miran la forma de los trazos, y una LSTM, que mira hacia los dos lados del renglón, suma el contexto. La red avanza por la tira de a 4 píxeles y en cada paso dice qué letra cree ver, o «nada».

Para pasar de pasos a letras, se juntan las repeticiones y se borran los «nada» (esto se llama decodificación CTC). Si en un tramo la letra más probable no llega al 50 %, la app no se la juega y escribe ?.

····
ב
100%
···
נ
98%
·
ח
45%
···
כ
39%
···
ה
54%
·

↓ se juntan las repeticiones y se borran los «nada»

Leyó
בנ??ה
En el sefer
מנחלת
·
אא
100%
··
ח
99%
··
ז
85%
·
ת
100%
··
ם
100%
··

↓ se juntan las repeticiones y se borran los «nada»

Leyó
אחזתם
En el sefer
אחזתם
· nada (cada casillero es un paso de 4 píxeles)menos del 50 %, queda como ?igualletras que se confunden?distinta
Las dos primeras palabras del renglón 5 de la foto. Abajo de cada recorte está lo que dijo la red en cada paso, con su probabilidad. Después vienen las letras que quedan y, abajo de todo, las del sefer.

En la primera palabra, la red leyó ב donde dice מ, y ה donde dice ת (dos letras que en STA"M se parecen). En otras dos letras dudó, y quedaron como ?. En la segunda palabra, la א aparece en dos pasos seguidos y cuenta como una sola, y la palabra sale perfecta.

La red no se sabe la Torá de memoria. Se entrenó solo con fotos sintéticas, armadas con columnas reales escritas con fuentes STA"M y envejecidas por computadora, con manchas, sombras, reflejos y curvas. En un 30 % de esas fotos las palabras estaban mezcladas al azar. De esa forma, la red no puede adivinar la palabra siguiente por el contexto y tiene que leer cada letra. Cómo se arman esas fotos, y cómo la probamos con sifrei reales que nunca vio, está en Cómo entrenamos la red que lee el sefer.

Por eso se equivoca bastante. Sobre la foto está lo que leyó en cada renglón, y hay mucho naranja, sobre todo abajo, donde la foto está más borrosa. Sin embargo, para el paso siguiente no hace falta una lectura perfecta.

Cada palabra leída, pintada donde la leyó la red. Verde: igual que en el sefer. Amarillo: letras que se confunden, o con ?. Rojo: distinta. Gris: sobra. Punteado: quedó afuera de la comparación.

Paso 7Buscar entre 80.316 palabras

Lo leído tiene errores, como יהות en vez de יהוה o ביואב en vez de מואב. Por lo tanto, buscar el texto tal cual no serviría. En cambio, cada palabra leída vota dónde empieza la foto. Esta parte ya pasa en el servidor, que recibe el texto y no la foto.

Por ejemplo, לערים es la palabra 39 de lo leído, y en la Torá está en la posición 65.300. Entonces vota que la foto empieza en la posición 65.262. Las palabras raras pesan más que las comunes (לערים aparece 2 veces en toda la Torá, y את, 2.622 veces), y las palabras parecidas también votan, un poco menos. Con 216 palabras votando, los votos se amontonan en un solo lugar.

BereshitShemotVaikráBamidbarDevarim← Masei→ Bereshit
Los votos de las palabras leídas, a lo largo de toda la Torá. Casi todos caen en un solo punto, al final de Bamidbar.

Alrededor de los lugares más votados, la app compara palabra por palabra, como cuando se comparan dos versiones de un mismo texto. Esa comparación tiene en cuenta que en letra STA"M es fácil confundir ב con כ, ד con ר o ה con ח, y que ? puede ser cualquier letra, así que esos errores cuestan poco.

וידבר
וידבר
יהות
יהוה
אל
אל
בשה
משה
מערבת
בערבת
ביואב
מואב
על
על
ירידן
ירדן
ירחו
ירחו
לא?ר
לאמר
צו
צו
אה
את
בני
בני
יקיראל
ישראל
ונדנו
ונתנו
?קכם
—
בנ??ה
—
אחזתם
אחזתם
ערים
ערים
לשבה
לשבת
ו??רשי
ומגרש
לערים
לערים
סביבתיהם
סביבתיהם
תתני
תתנו
ללוים
ללוים
והיו
והיו
הערים
הערים
להם
להם
לשבת
לשבת
אב Leyó · אב En el seferigualletras que se confundencon ?distintasobra
Cuatro renglones de la foto. Arriba está lo que leyó la red y abajo, lo que dice el sefer. Sobre la foto se usan los mismos colores para todos los renglones.

Paso 8¿Está segura?

Encontrar un lugar no alcanza para dar una respuesta. La app pide un mínimo de palabras alineadas en más de un renglón y compara el mejor lugar con el segundo. Acá el mejor (Masei, columna 198) sacó 147,2 puntos contra 15 del segundo, con 179 palabras alineadas en 27 renglones.

Mejor lugar: Masei, columna 198147,2
Segundo15
El puntaje de la alineación del mejor lugar contra el del segundo.

Cuando los dos primeros se parecen, la app no adivina. Esto pasa, por ejemplo, en Bamidbar 7, donde la ofrenda de cada uno de los doce nesiim se repite casi igual. En ese caso, la app muestra las opciones y pide otra foto, mejor si se ve el principio de la columna. En 2.000 pruebas simuladas con hasta la mitad de las letras mal leídas, nunca dio un lugar equivocado con confianza.

Paso 9Para qué lado mover el sefer

El resultado de todo esto es una posición en palabras, que sirve para cualquier sefer. Para contar columnas, la app usa el formato estándar de 245 columnas. Esta foto es de la columna 198, y Devarim 1:1 está en la 200.

Como el texto va de derecha a izquierda, ir hacia Devarim es ir hacia la izquierda, en este caso 2 columnas. Si el sefer sigue el formato estándar, la cuenta es exacta. Si no, es una aproximación, y conviene volver a escanear. Al llegar, la app te dice en qué renglón empieza la lectura.

196197198199200201Acá está abiertoDevarim 1:12 columnas
Las columnas alrededor de la foto, de derecha a izquierda como en el sefer.

¿Qué se manda al servidor?

El texto leído y algunos datos del escaneo (cuánto tardó, qué lectura buscabas y un número al azar que identifica al teléfono). La foto se queda en el teléfono, salvo que alguien la mande a propósito para ayudar a mejorar la red.

Lo que todavía no hace bien

  • Las dos canciones escritas en forma de ladrillos, Shirat HaIam y Haazinu, porque el buscador de renglones no las sigue.
  • Los pasajes que se repiten, como el de los nesiim. Ahí la app avisa que hay más de una opción en lugar de elegir una.
  • Los sifrei que no siguen el formato estándar. La app cuenta las columnas siempre con el formato estándar de 245 columnas, y todavía no detecta cuando un sefer tiene otro. En esos sifrei la cuenta puede no coincidir, así que conviene escanear de nuevo cuando llegás.

El código

El código es abierto y está en GitHub. Los resultados de cada prueba están en la evaluación, y el script que generó las figuras de este artículo está en tools/eval. Ese script corre en una computadora el mismo código que la app corre en el teléfono. Las sumas de tinta de los pasos 3 y 4, los votos y la comparación palabra por palabra están recalculados con el mismo método para poder dibujarlos.