Usando un árbol binario en swift con enum usando OCR como ejemplo

El objetivo era crear una aplicación para Mac que pueda reconocer el código de imágenes y videos.

Quería asegurarme de que, incluso con una gran cantidad de código, el texto fuera reconocido en menos de un segundo.

El problema se ve facilitado por el hecho de que el idioma en el que se escribe el código es siempre inglés y el ancho entre todas las letras es el mismo (fuente monoespaciada): se utilizan para la programación, y en estas fuentes es fácil ver la diferencia entre 1 y I, 0 y O, etc.

En resumen, la tarea se reduce a dos partes:

1. Encontrar la letra misma con sus bordes


Y Vision, el nuevo marco de Apple, hizo un gran trabajo.

Aquí hay una captura de pantalla de cómo funciona.


2. Reconocimiento de la letra en los límites dados.


Decidí no ir de una manera engañosa y verificar ciertos píxeles del cuadrado, dentro de los límites de los cuales hay letras (digamos: centro, esquinas, lados) y, a partir de la presencia o ausencia de una letra, clasificar qué es la letra.

Ejemplo ilustrativo:



Y así es como se verá el árbol
Esta es una parte ya que todo no encajaría, y no es necesario.


¿Cómo transferir este dibujo esquemático al código, para no excavar en él y para que sea tan obvio?

Aquí es donde un árbol binario viene al rescate. Aquí está su marco.

enum Tree<Node, Result> { ///Empty result case empty ///Result with generic type case r(Result) ///Recursive case with generic tree indirect case n(Node, Tree<Node, Result>, Tree<Node, Result>) } 

Ahora, en base a ello, podemos transferir todo nuestro dibujo al código.

 //.c ,       ,   "H"    "O" //  .c   ,     let HorOTree = TreeOCR.n(.c, .r("H"), .r("O")) 

Así es como una pieza de madera se vería más grande.



Puede descomponer todo de manera muy esquemática y encontrar fácilmente la letra que necesita.

Y en el último momento, así es como se ve el modelo en sí, en el que se lleva a cabo todo el trabajo.

 extension Tree where Node == OCROperations, Result == String { func find(_ colorChecker: LetterExistenceChecker, with frame: CGRect) -> String? { switch self { case .empty: return nil case .r(let element): return element case let .n(operation, left, right): let exist = operation.action(colorChecker, frame) return (exist ? left : right).find(colorChecker, with: frame) } } } 

En este árbol, pasamos la clase LetterExistenceChecker, que es responsable de verificar la presencia de un píxel de una letra en cierto punto dentro de los límites del cuadrado deseado. Por supuesto, omití muchos detalles, de lo contrario el artículo sería demasiado engorroso. Y aquí, no solo estas dos etapas que se mencionaron en el artículo, sino mucho más, pero se omitieron, porque el objetivo era mostrar cómo usar el árbol binario y la enumeración.

Aquí hay una demostración de cómo funciona el programa, tenga en cuenta que dado que el objetivo era reconocer solo texto con código, decidí ignorar todo el resto del texto que no es código, de modo que el programa solo buscaría texto con código.


Estaré encantado de escuchar sus comentarios, críticas.

Source: https://habr.com/ru/post/439324/


All Articles