5.2. Coordenadas y regiones¶
El procesamiento de imágenes actúa sobre píxeles, y para actuar sobre un píxel un algoritmo tiene que direccionarlo por coordenada. Para actuar sobre un rectángulo de ellos, ocurre lo mismo: el rectángulo tiene que describirse de una manera en la que el algoritmo y el código de la aplicación coincidan. La convención que el módulo image usa para coordenadas y rectángulos es sencilla, con un detalle que sorprende a los lectores habituados a la convención matemática en lugar de a la convención de los gráficos por computadora, y que conviene dejar explícito desde el principio.
5.2.1. La cuadrícula de píxeles¶
El píxel (0, 0) es la esquina superior izquierda de una imagen. El eje x avanza hacia la derecha, de modo que una x mayor significa más a la derecha. El eje y avanza hacia abajo, de modo que una y mayor significa más abajo en la imagen. Una imagen de ancho por alto contiene píxeles en coordenadas enteras desde (0, 0) hasta (width - 1, height - 1); no hay ningún píxel en (width, 0) ni en (0, height): esas posiciones son los bordes derecho e inferior, un paso más allá del último píxel real en cada dirección.
El eje y descendente es el detalle mencionado más arriba. Un lector habituado a la geometría del papel cuadriculado espera que una y mayor signifique más arriba; aquí esa intuición está exactamente invertida. La razón de la inversión es que tanto los sensores digitales como las pantallas digitales trabajan desde la esquina superior izquierda y recorren cada fila hacia la derecha, de arriba abajo, y disponer los píxeles en memoria en ese mismo orden hace que la relación entre «la posición i en el búfer» y «la fila r, columna c de la imagen» sea la aritmética más simple posible: la posición i del píxel (x, y) es simplemente y * width + x. Toda biblioteca de imágenes acordó esa disposición hace décadas por la misma razón, y el coste es un pequeño ajuste mental al trabajar por primera vez con imágenes.
El sistema de coordenadas de la imagen: origen en la esquina superior izquierda, x avanzando hacia la derecha, y avanzando hacia abajo. Una región rectangular dentro de la imagen se nombra por su esquina superior izquierda (x, y) y sus dimensiones (w, h).¶
5.2.2. Rectángulos¶
A la mayoría de las operaciones sobre una imagen les importa menos un solo píxel que un rectángulo de píxeles: un área en la que mirar, una región que copiar, un fotograma dentro de un fotograma sobre el que calcular estadísticas. La forma de nombrar un rectángulo elige la extensión más simple posible de la convención de un solo píxel: dar la coordenada de la esquina superior izquierda, seguida de las dimensiones del rectángulo, empaquetadas en una tupla de cuatro elementos (x, y, w, h). Los píxeles dentro del rectángulo están en las columnas x hasta x + w - 1 y en las filas y hasta y + h - 1.
El detalle que conviene dejar explícito aquí es que w y h son tamaños, no coordenadas de la esquina inferior derecha. El rectángulo (10, 20, 4, 3) cubre las columnas 10, 11, 12, 13 y las filas 20, 21, 22 – doce píxeles en total – no una región que va desde (10, 20) hasta (4, 3). La convención es uniforme en todo el módulo, así que una vez interiorizada los errores cesan, pero sí sorprende a la gente la primera vez.
La forma (x, y, w, h) aparece en tres lugares que parecen distintos pero comparten la convención. El primero es cuando una imagen describe su propia extensión: el rectángulo que cubre toda la imagen es (0, 0, width, height). El segundo es cuando un método de detección devuelve un resultado con un cuadro delimitador – un blob, un rect, una apriltag – y el cuadro se informa como (x, y, w, h). El tercero es cuando hay que indicarle a un método que trabaje sobre una subregión de la imagen en lugar de sobre todo el fotograma; el argumento de palabra clave roi que delimita la operación toma la misma tupla de cuatro elementos.
Tomar un cuadro delimitador de un método y pasarlo al roi del siguiente método es uno de los patrones más comunes en el procesamiento de imágenes. El cuadro delimitador de una primera detección gruesa reduce el área de búsqueda para una segunda más fina, y el vocabulario uniforme entre los resultados de detección y los argumentos de los métodos es lo que hace que ese patrón sea tan directo como es: una sola forma de tupla, usada de la misma manera a ambos lados del traspaso.
5.2.3. Direcciones enteras, centroides fraccionarios¶
Las direcciones de los píxeles en sí mismas son enteros. Un píxel o bien está o bien no está en una columna y fila enteras dadas, y preguntar qué hay en la coordenada (40.5, 30.7) no es una pregunta bien formulada: no hay ningún píxel situado exactamente en esa posición. No obstante, un puñado de magnitudes que el módulo image deriva de las posiciones de los píxeles son fraccionarias, y conviene entender por qué para que la distinción no sorprenda a la aplicación más adelante.
El caso más común es el centroide: el centro de masa de una región. Para una región conexa de píxeles, el centroide en forma de coma flotante es el promedio de las posiciones de los píxeles que la componen, ponderado por su densidad. Una región cuyos píxeles se reparten entre dos columnas tendrá un centroide x de, por ejemplo, 41.6 – una posición real que el ojo describiría como «el centro de esa región» aunque ningún píxel real se sitúe exactamente en esa x. Los objetos de resultado de detección llevan ambas formas como propiedades de solo lectura: un par entero (cx / cy, útil al realimentar la posición hacia algo que quiere coordenadas de píxel enteras) y un par de coma flotante (cxf / cyf, útil cuando la posición va a un bucle de control que se beneficia de una resolución de subpíxel).
El otro caso es el desplazamiento entre dos fotogramas medido en el dominio de la frecuencia. Las técnicas que analizan el contenido espectral de una imagen en lugar de sus píxeles directamente pueden resolver desplazamientos más finos que un píxel, y los informan como valores de coma flotante (dx, dy).
La regla práctica: las direcciones de los píxeles son enteros; las posiciones y los desplazamientos que salen de un algoritmo pueden ser de coma flotante. Los métodos de dibujo aceptan cualquiera de las dos formas y redondean los valores de coma flotante hacia abajo al píxel entero más cercano cuando el resultado tiene que caer sobre la cuadrícula.
5.2.4. Cartesianas y polares¶
El sistema descrito hasta ahora es cartesiano: cada píxel se nombra por su desplazamiento horizontal y vertical respecto al origen. Ese es el sistema en el que se almacenan los bytes – el píxel i del búfer corresponde al píxel en la columna i % width y la fila i // width, recorriendo las filas desde arriba – y es el sistema en el que opera cada método de manera predeterminada.
Conviene conocer una segunda representación porque algunos algoritmos funcionan mucho mejor en ella. Las coordenadas polares nombran cada píxel por su distancia a un punto central elegido y el ángulo entre él y una dirección de referencia. Los píxeles de la imagen no se han movido – los bytes siguen estando en el mismo búfer en orden de filas – pero el esquema de direccionamiento ha cambiado de «cuánto a la derecha y cuánto hacia abajo» a «a qué distancia del centro y con qué ángulo a su alrededor.»
El mismo punto P, nombrado de dos maneras: cartesiana (x, y) desde el origen superior izquierdo, polar (r, theta) desde un centro elegido.¶
¿Por qué molestarse en cambiar? Por dos identidades que convierten búsquedas difíciles en búsquedas fáciles.
En coordenadas polares, rotar la imagen alrededor del centro elegido es la misma operación que trasladar sus píxeles a lo largo del eje del ángulo – la dirección x en la imagen reproyectada. Una copia rotada es la original desplazada a la izquierda o a la derecha en forma polar.
En la variante log-polar – el eje de la distancia usa una escala logarítmica, el eje del ángulo se mantiene lineal – escalar la imagen alrededor del centro elegido es la misma operación que trasladar sus píxeles a lo largo del eje de la distancia – la dirección y. Una copia escalada es la original desplazada hacia arriba o hacia abajo en forma log-polar.
Así, un algoritmo que tenga que reconocer un patrón conocido bajo rotación o escala puede hacer su búsqueda en el espacio polar, donde ambas transformaciones se convierten en traslaciones ordinarias. Las traslaciones son mucho más baratas de buscar que las rotaciones y las escalas, y la reproyección polar es lo que hace disponible esa sustitución.
Las coordenadas polares no reemplazan a las cartesianas para almacenar píxeles; los bytes siempre residen en la cuadrícula cartesiana. El módulo proporciona un par de métodos que reproyectan una imagen de la forma cartesiana a la polar bajo demanda, el algoritmo que necesita coordenadas polares hace su trabajo, y o bien el resultado se reproyecta de vuelta o la medición en el espacio polar se usa directamente. Ese mecanismo es la única razón por la que las coordenadas polares aparecen en algún lugar de la superficie del módulo.
Con las coordenadas cartesianas para nombrar píxeles individuales, la tupla de cuatro elementos (x, y, w, h) para nombrar rectángulos de ellos, y las coordenadas polares disponibles cuando un algoritmo se beneficia de ellas, una aplicación dispone de un vocabulario completo para nombrar dónde en una imagen está algo. Lo que realmente se almacena en cualquiera de esas posiciones es la siguiente capa de los fundamentos.