5.21. Escalar, voltear y recortar¶
Todas las subsecciones anteriores trabajaban sobre los píxeles en las mismas posiciones en las que empezaban. La familia de transformaciones cambia eso. El escalado envía cada píxel de entrada a una posición de salida distinta, posiblemente a varias posiciones de salida a la vez (al ampliar) o a una posición compartida con otros varios píxeles de entrada (al reducir). Voltear y rotar hacen lo mismo a través de un mapeo diferente. El recorte conserva un subconjunto rectangular de los píxeles de entrada y descarta el resto.
El módulo image expone esa familia mediante tres métodos que comparten la mayor parte de sus argumentos y de su comportamiento:
copy()– produce una copia de la imagen, posiblemente escalada, recortada o reorientada.crop()– la misma operación quecopy, pero con la expectativa de que la aplicación va a extraer un subrectángulo de la fuente.scale()– lo mismo de nuevo, con la expectativa de que la aplicación va a redimensionar el resultado.
Los tres comparten los mismos argumentos y la misma maquinaria de transformación; la diferencia está en dónde acaba el resultado por defecto. copy() produce una imagen nueva, mientras que crop() y scale() modifican la fuente en su sitio.
5.21.2. Interpolación: AREA, BILINEAR, BICUBIC¶
Cuando el escalado envía cada píxel de salida a una posición que no se alinea con ningún píxel de entrada concreto, el método tiene que decidir qué valor escribir. Tres banderas controlan cómo:
image.BILINEAR interpola entre los cuatro píxeles de entrada más cercanos ponderados por su distancia a la posición de salida. El resultado es más suave que el del vecino más cercano, sin dientes de sierra visibles en las líneas diagonales, pero la aritmética adicional cuesta unas cuatro veces lo que una pasada de vecino más cercano. Es la elección adecuada para la mayoría del trabajo de ampliación y para cualquier factor de escala no entero.
image.BICUBIC interpola entre los dieciséis píxeles de entrada más cercanos usando una curva cúbica, lo que produce resultados aún más suaves a costa de nuevamente más aritmética. La mejor calidad para las aplicaciones sensibles al coste que la necesitan; rara vez vale la pena el cómputo adicional para los fotogramas en vivo que el IDE solo va a mostrar.
image.AREA promedia todos los píxeles de entrada que caen dentro de la huella del píxel de salida – el algoritmo adecuado para reducir. Bilinear y bicubic son interpoladores: estiman un valor entre los píxeles de la fuente, que es lo que la ampliación necesita, pero al reducir cada píxel de salida cubre muchos píxeles de la fuente y un interpolador lee solo los pocos más cercanos – el detalle que se salta vuelve en forma de aliasing. image.AREA en cambio incorpora todos los píxeles cubiertos al promedio.
El algoritmo de escalado por defecto sin ninguna pista (hint) es el del vecino más cercano, que es el más barato y la respuesta correcta cuando la fuente ya está a la resolución de píxel del destino.
5.21.3. Orientación: volteos y rotaciones¶
Las banderas de orientación son un pequeño conjunto de transformaciones booleanas que se componen libremente entre sí y con las banderas de interpolación:
image.VFLIPvoltea la imagen verticalmente (la parte superior pasa a ser la inferior).image.HMIRRORla refleja horizontalmente (la izquierda pasa a ser la derecha).image.TRANSPOSEintercambia los ejes x e y (las filas pasan a ser columnas).
La mayoría de las rotaciones surgen de componer esas tres. El módulo también expone atajos con nombre:
image.ROTATE_90(=VFLIP | TRANSPOSE)image.ROTATE_180(=HMIRROR | VFLIP)image.ROTATE_270(=HMIRROR | TRANSPOSE)
En código:
img.copy(hint=image.ROTATE_90, copy_to_fb=True)
5.21.4. Manejo de la relación de aspecto¶
Cuando la relación de aspecto de la fuente no coincide con el rectángulo en el que se está dibujando, tres banderas deciden qué hacer con el desajuste:
image.SCALE_ASPECT_KEEP preserva la relación de aspecto de la fuente y aplica letterboxing al resultado – la fuente se escala hasta que cabe dentro del destino, rellenando el resto del destino con píxeles vacíos (en cero). Es la elección adecuada cuando mantener la fuente sin distorsionar importa más que llenar toda la salida.
image.SCALE_ASPECT_EXPAND preserva la relación de aspecto de la fuente y la recorta – la fuente se escala hasta que llena el destino, cortando las partes que sobresalen más allá del destino. Es la elección adecuada cuando llenar toda la salida importa más que ver cada parte de la fuente.
image.SCALE_ASPECT_IGNORE ignora la relación de aspecto y estira la fuente para llenar el destino, aceptando cualquier distorsión que esto introduzca. Es la elección adecuada cuando la aplicación ya ha tenido en cuenta la distorsión – cuando las dimensiones del destino no son en realidad un rectángulo de la misma escena, por ejemplo.
El valor por defecto (sin ninguna bandera de aspecto establecida) es el mismo que SCALE_ASPECT_IGNORE: estirar para llenar. Las aplicaciones a las que les importa la relación de aspecto especifican una de las tres de forma explícita.
5.21.5. Cuándo recurrir a cada cual¶
La mayoría de los redimensionamientos usan scale() con un par x_scale / y_scale y una pista de interpolación:
img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)
La mayoría de las rotaciones usan la misma llamada con hint=image.ROTATE_90 o similar.
El recorte usa crop() con un roi distinto del valor por defecto:
img.crop(roi=(40, 30, 200, 150))
Cuando la fuente tiene que sobrevivir a la operación – al capturar un fotograma de referencia, al tomar una miniatura de un fotograma que está a punto de procesarse de forma destructiva – copy() produce el resultado como una imagen nueva y deja la fuente intacta:
thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)
Ese valor por defecto es la verdadera diferencia detrás de los tres nombres: scale y crop transforman en su sitio, copy reserva memoria. Las palabras clave de colocación del resultado salvan la distancia: copy=True en scale o crop reserva el resultado como un búfer separado en el heap en lugar de sobrescribir la fuente, y copy_to_fb=True en cualquiera de los tres lo deposita en el búfer de fotogramas (frame buffer) para la vista previa del IDE.