⚠️ Este es un sitio de traducción no oficial, sin relación con ImageMagick Studio LLC. Para información autorizada, consulte la página original (https://usage.imagemagick.org/distorts/index.html).

Ejemplos de ImageMagick -- Distorsionar imágenes

Tras haber visto el conjunto sencillo de operadores integrados de envoltura y distorsión de imágenes que IM ofrece desde sus inicios, aquí profundizamos y examinamos la mecánica interna y las distorsiones matemáticas más complejas de las imágenes. A partir de esta comprensión más profunda, pasamos luego a un operador de distorsión de imágenes más generalizado. Esto incluye distorsiones que van desde rotaciones, escalados y cizallamientos complejos, a distorsiones de perspectiva o 3D, al curvado hacia y desde arcos circulares, a distorsiones de lente de cámara, y finalmente a distorsiones más generales del tipo morph.


Técnicas generales de distorsión

Ahora que conocemos los sencillos operadores de distorsión que IM ofrece, demos un paso atrás y veamos los detalles más concretos, cómo funcionan realmente las distorsiones de imágenes y cómo puedes mejorar la forma de usarlas. Más adelante avanzaremos hacia métodos mucho más complejos de distorsión de imágenes, incluidos métodos que no están integrados directamente en ImageMagick. Solo hay unas pocas formas básicas en que un procesador de imágenes puede distorsionarlas. Los operadores de Distorsión simple, por ejemplo, se logran mediante el intercambio de píxeles. Es decir, píxeles individuales o incluso filas y columnas enteras de píxeles simplemente se intercambian de posición para Voltear, Desplazar, Transponer e incluso Rotaciones rectangulares de imágenes. No se realizan cambios de color y el número de píxeles permanece igual. El siguiente método para distorsionar imágenes consiste en desplazar o cizallar las columnas y filas de píxeles, ya sea horizontal o verticalmente, como lo que hace IM con el Cizallamiento de imágenes y la Distorsión de onda mencionada antes. Los cizallamientos, a su vez, proporcionan un método para Rotar imágenes según cualquier ángulo dado, de una manera que debería ser bastante rápida. Sin embargo, los métodos de desplazamiento de píxeles se limitan a esas distorsiones básicas. No pueden escalar una imagen a un tamaño diferente, por ejemplo. También tienes muy poco control sobre el tratamiento de las áreas de la imagen resultante que no quedaron cubiertas por la imagen de origen original. En las funciones mencionadas, IM simplemente fija las áreas faltantes al color de fondo actual. Para poder distorsionar imágenes de una manera mucho más general, necesitas usar una técnica de distorsión más general conocida como Mapeo inverso de píxeles. Por ejemplo, este método lo emplean las Distorsiones circulares más complejas, como Implosionar y Arremolinar imágenes.

Mapeo de píxeles directo o hacia delante

Lo primero que se le ocurre a la gente cuando intenta distorsionar una imagen es tomar cada píxel de la imagen de origen y moverlo directamente a su nueva ubicación en la imagen de destino. De hecho, esto es más o menos lo que ocurre con las Distorsiones simples, el Recorte de imágenes e incluso con la distorsión de imágenes vectoriales. Cada píxel (o coordenada) simplemente se mueve a su nueva posición en la imagen final. Por desgracia, esto tiene problemas cuando intentas hacerlo para algo que no sea una distorsión simple. Por ejemplo, aquí tomo una lista de píxeles enumerados de una imagen pequeña y solo cambio la ubicación de cada píxel, para rotarla a su nueva posición. |

  # Rotate by 17 degrees -- get the Sine and Cosine of this angle
  sin=`magick xc: -format "%[fx:sin( 17 *pi/180)]" info:`
  cos=`magick xc: -format "%[fx:cos( 17 *pi/180)]" info:`

  # For each Pixel, rotate that pixels coordinates
  magick koala.gif  txt:- |  sed '2,$ s/,/:/' |\
    gawk -F: 'NR == 1 { print }
              NR > 1 {  x = $1-32;    y = $2-32;
                        nx = int( c*x - s*y + 32 );
                        ny = int( s*x + c*y + 32 );
                        printf( "%d,%d: %s\n", nx, ny, $3 );
              }' s=$sin c=$cos - |\
      magick -background black  txt:-   koala_rotated_direct.gif

[IM Output]
La distorsión es una simple rotación de tan solo 17 grados, pero los resultados no son nada buenos. En primer lugar, cada nueva ubicación de píxel es un valor en coma flotante, pero los píxeles solo pueden existir en una rejilla de números enteros, de modo que lo anterior simplemente descarta la parte fraccionaria no entera de los resultados. El segundo problema es que el resultado está lleno de huecos donde no aterrizó ningún píxel. Lo que nos lleva al tercer problema. Puede que no lo veas, pero por cada hueco de la imagen resultante encontrarías también otra ubicación donde se colocaron dos píxeles. Es decir, tienes varios píxeles en la misma ubicación. ¿Qué valor de píxel deberías usar? En lo anterior, IM simplemente usó el último píxel definido para una ubicación. Dicho de otro modo, la imagen resultante está incompleta, donde cada píxel del destino no está exactamente donde debería estar y podría tener varios píxeles, o ningún píxel en absoluto. Estos son problemas graves, y uno que no se puede resolver fácilmente al mapear hacia delante los píxeles de la imagen de origen directamente a la imagen de destino. Esto no quiere decir que no pueda funcionar, y muchos artículos de investigación hablan de usar una técnica conocida como 'splatting '. Básicamente toman cada píxel de entrada, transforman su ubicación y luego lo dibujan con una difusión y mezcla apropiadas de los colores de los píxeles en la nueva ubicación. Esta técnica es especialmente útil al tratar con la digitalización 3D de objetos del mundo real. Aquí tienes una 'nube' de puntos de superficie de color conocido. Cualquier punto visible para el usuario simplemente se 'salpica' (splatted) en la pantalla para formar una imagen final. Con suficientes puntos, la imagen se verá completa. Con controles 3D interactivos, funciona muy bien y es muy rápido. No obstante, salpicar puntos tridimensionales queda fuera del ámbito de IM, que se ocupa de imágenes ráster 2D.

Mapeo inverso de píxeles

En lugar de intentar mapear los píxeles hacia la imagen final, puedes mapear la coordenada de cada píxel de la imagen de destino a la ubicación correspondiente en la imagen de origen y, a partir de la imagen de origen, buscar el color que ese píxel debería contener. Esto se conoce como Mapeo inverso de píxeles y es lo que hace prácticamente todo programa de distorsión de imágenes. Como cada píxel de la imagen de destino se procesa uno por uno, podemos estar seguros de que cada píxel del destino obtiene un único color. Así, mientras podamos averiguar la ubicación de 'origen' para cada píxel de destino, podemos distorsionar una imagen de origen hacia la imagen de destino usando cualquier fórmula matemática que puedas imaginar.

[Diagram]

En resumen, un mapeo de distorsión (mapeo inverso) hace lo siguiente.

For each pixel (I,J) in the destination or output image
   Map the I,J pixel position to a X,Y pixel position in the original image
   Look up the Color of the original image at position X,Y
       Using color interpolation, work out the appropriate color.
       Or the virtual-pixel setting, if it misses the actual source image.
   Set the destination images color for pixel I,J

Ten en cuenta que arriba usé los nombres de variable 'I,J' y 'X,Y', ya que estas variables se corresponden con los nombres de variable que normalmente usarías en el Operador FX DIY. Por ejemplo, aquí simulo la misma rotación de 17 grados que intenté antes, pero esta vez uso el operador "[-fx](https://imagemagick.org/command-line-options/#fx)" para buscar el píxel más cercano a esa ubicación en la imagen de origen. |

  # Rotate by 17 degrees -- get the Sine and Cosine of this angle
  sin=`magick xc: -format "%[fx:sin( 17 *pi/180)]" info:`
  cos=`magick xc: -format "%[fx:cos( 17 *pi/180)]" info:`
  cx=37; cy=37;   # center of rotation

  magick -size 75x75 xc:       koala.gif  \
          -virtual-pixel Black  -interpolate NearestNeighbor \
          -fx "ii = i - $cx;   jj = j - $cy;
               xx =  $cos*ii +$sin*jj + $cx;
               yy = -$sin*ii +$cos*jj + $cy;
               v.p{xx,yy}" \
          koala_rotated_fx.gif

[IM Output]
Puedes obtener más detalles sobre el ejemplo DIY anterior en la subsección Mapeo de distorsión afín DIY. Como puedes ver, ya no tenemos 'huecos' en nuestra imagen, pues se busca un color para cada píxel del destino. Sigue sin verse muy bien, pero eso es cuestión de ajustar exactamente qué color debería colocarse en cada píxel. Es decir, el mapeo inverso de píxeles no genera huecos ni píxeles superpuestos. Cada píxel tiene un color debidamente definido que produce una imagen completa.
La distinción entre mapeo directo e inverso es importante, ya que la mayoría de las transformaciones matemáticas se definen como mapeos directos, que mapean una única posición de origen (X,Y) a una posición de destino (I,J). Y, en efecto, un 'mapeo directo' funciona bien para gráficos vectoriales y para dibujar líneas, donde basta con mapear los extremos de la línea y dibujarla. Esto es especialmente cierto para cualquier transformación lineal, como las rotaciones, donde las líneas permanecen rectas. Es de hecho lo que se hace en todos los lenguajes basados en vectores, como postscript y SVG. Pero para una imagen ráster general, debes usar un 'mapeo inverso' para distorsionar la imagen, de modo que puedas tener la certeza de 'rellenar' todos los píxeles de la imagen de destino. Por ejemplo, si miras las matemáticas que se usaron para mapear las coordenadas en los dos casos anteriores, verás que son casi exactamente iguales. El mapeo inverso de un 'rotar' es otro 'rotar', solo que en la dirección opuesta. Si te fijas bien, verás que la constante 'sin' está negada respecto a la versión mapeada hacia delante, y eso basta para invertir la dirección de la rotación. Este detalle es importante y crítico. El problema es que no todas las transformaciones de mapeo directo funcionan bien como transformación invertida. De hecho, algunos mapeos directos no tienen mapeos inversos directos sencillos. Esto no quiere decir que no se pueda hacer, solo que no de forma sencilla. Por otro lado, algunas transformaciones de imagen funcionan muy bien como mapeo inverso, pero no tienen mapeos directos sencillos. Así que usar el método de mapeo inverso es bueno y malo a la vez en términos matemáticos.
A modo informativo, aquí está el equivalente más rápido a lo anterior usando un método de Distorsión general, SRT que realiza exactamente la misma rotación de la imagen que se hizo antes, produciendo exactamente el mismo resultado, solo que más rápido. De nuevo, la búsqueda de color se restringe únicamente al color del píxel más cercano a la posición mapeada usando la interpolación 'point'. Esto significa que no se añaden colores nuevos a la imagen (salvo cuando 'fallamos' la imagen de origen), pero también obtienes efectos de aliasing severos. |

  magick koala.gif  -virtual-pixel Black  -interpolate NearestNeighbor \
          -filter point    -distort SRT 17    koala_rotated_srt.gif

[IM Output]
| Para una discusión alternativa sobre las transformaciones de distorsión, consultaLeptonica, Affine Implementation y, en concreto, su discusión sobre el método 'point-wise'. El otro método, 'sequential', es esencialmente cómo IM implementaba antes sus operadores de distorsión Rotar y Cizallar.
---|---
¿Qué hay en un nombre? Durante mi estudio descubrí que no existe una nomenclatura realmente clara para este método de procesamiento de imágenes. El proceso algorítmico en sí se conoce como 'Mapeo inverso de píxeles ', mientras que el uso de ecuaciones matemáticas se conoce como 'Transformación geométrica '. Si la distorsión se controla mediante el movimiento de varios puntos de control, a menudo se conoce como 'Curvado de imágenes ' o 'Rubber Sheeting '. El proceso de definir puntos específicos, normalmente para encontrar puntos equivalentes entre dos o más imágenes, se conoce como 'Registro de imágenes '. Las imágenes también pueden subdividirse en unidades más pequeñas y simples que se distorsionan individualmente mediante una técnica llamada 'Gridding ' (cuadriláteros) y 'Malla triangular ' (triángulos). Usando pequeñas distorsiones incrementales con mezcla de colores de dos imágenes, puedes generar 'Morphs de imágenes ' animados como los que ves en películas y videos musicales. Si se usa una imagen de mapeo previamente preparada en lugar de una búsqueda matemática al vuelo, obtienes un 'Mapeo de distorsión absoluto '; si la búsqueda es un desplazamiento relativo (siendo el gris al 50% ningún desplazamiento ni cambio de la coordenada de búsqueda), obtienes un 'Mapeo de desplazamiento '. Si el mapeo solo modifica ligeramente el color (sombreado) en lugar de hacer búsquedas de distorsión, obtienes el relacionado pero distinto 'Mapeo de superficie por relieve (bump) '. En el modelado 3D, y en los juegos de computadora 3D, las mismas técnicas también se usan para dar algún tipo de patrón coloreado a superficies planas y curvas mediante un método conocido como 'Mapeo de texturas '. Esto puede implicar subdividir imágenes en rejillas y mallas que se aproximan a un solo píxel. Luego tienes la visualización de un objeto definido en términos de millones de puntos individuales mediante una técnica llamada 'Point Splatting ', aunque eso normalmente se aplica usando una distorsión de mapeo directo. Todo lo anterior está muy estrechamente relacionado, y en lo más básico implica la búsqueda del color de un píxel basándose en mapear una coordenada final de destino a la imagen (u objeto) de origen. Es decir, mapear Destino a Origen. Qué término deberías usar... Elige el que prefieras.

Búsqueda del color de píxel

Todavía hay algunos problemas con la técnica anterior de Mapeo inverso de píxeles. En primer lugar, al mapear un píxel desde una posición entera fija del destino, puedes acabar en una posición no entera de la imagen de origen. Es decir, una ubicación que cae en algún punto entre los píxeles individuales de la imagen de origen. Para determinar qué color debe devolverse se usa un proceso llamado Interpolación, que determina el color final de esa posición real mezclando los colores de los píxeles circundantes. La configuración de Interpolación también gestionará el caso en que una parte de una imagen distorsionada se 'estira' de modo que un único píxel de origen acaba esparcido sobre una gran área de la imagen de destino. Sin embargo, el caso opuesto no lo maneja muy bien un método simple de interpolación. Y eso requiere otras técnicas que veremos más abajo. Por ejemplo, aquí volvemos a rotar nuestro koala, pero esta vez usamos una configuración "[-interpolate](https://imagemagick.org/command-line-options/#interpolate) [Mesh](misc.html#mesh)" para mezclar los cuatro píxeles cercanos y producir así un color mejor y más correcto de la búsqueda. |

  magick koala.gif  -virtual-pixel Black  -interpolate Mesh \
          -filter point    -distort SRT 17    koala_rotated_mesh.gif

[IM Output]
Como puedes ver, usando una simple fusión de tan solo los colores vecinos más cercanos que rodean el punto de búsqueda no entero, puedes mejorar mucho el aspecto de la imagen distorsionada. Pero hay otros problemas implicados... Por ejemplo, ¿qué haces cuando la posición mapeada 'falla' por completo la imagen de origen? En este caso, qué color debe devolverse lo determina la configuración de Píxel virtual. Esta configuración elegirá un color, como el del borde más cercano de la imagen de origen, fingirá que la imagen de origen está infinitamente repetida en mosaico (o en mosaico reflejado) por todo el plano, o usará algún color específico como 'white', 'black' o 'transparent', o el color de fondo definido por el usuario. También existe la posibilidad de que no haya una coordenada matemáticamente válida para una posición de destino concreta que se está mapeando. Por ejemplo, el píxel mira hacia el 'cielo' de un 'plano' en perspectiva (consulta Mirando horizontes lejanos) y, por tanto, ni siquiera ve el 'plano' en el que yace la imagen de origen. En este caso, un Píxel virtual resulta inútil, ya que no 'alcanza' el plano de la imagen de origen en un espacio N-dimensional y, como tal, ¡el píxel de destino es completamente inválido! En este caso IM usa la configuración "[-alpha set](https://imagemagick.org/command-line-options/#alpha)" actual para el color del píxel. Si es un 'fallo por poco', IM aplicará anti-aliasing a este color inválido con los colores vecinos del plano de la imagen, si sabe cómo. Lo hace para las distorsiones de perspectiva.

Supermuestreo

La interpolación funciona bien para distorsiones de imagen simples. Pero si una parte de la imagen de origen se comprime en un área mucho más pequeña, cada píxel de destino podría requerir en realidad la fusión de un área mucho mayor de la imagen de origen. Recuerda que los píxeles no son realmente puntos, sino que representan un área rectangular de una imagen real. Esto significa que, en algunos casos, deberíamos intentar comprimir un área grande de la imagen de origen en un único píxel de destino. Cuando esto ocurre, una simple Búsqueda de píxel fallará, ya que solo busca el color en un único 'punto' de la imagen de origen (usando la vecindad de píxeles circundante) y no fusiona ni combina todos los colores de la imagen de entrada que quizá haya que comprimir en ese único píxel. El resultado de esto es que un píxel de destino podría acabar con un color esencialmente aleatorio de la imagen de origen, en lugar de un promedio de todos los colores implicados. Esto no es malo en sí mismo, pero cuando todos los píxeles de un área hacen esto, obtienes imágenes con píxeles aparentemente aleatorios y aislados, efectos moaré y efectos de 'escalonamiento' por aliasing. Las líneas finas también empiezan a parecer más bien líneas de puntos y guiones (consulta los ejemplos del Operador Sample) o podrían desaparecer por completo. Todos estos efectos se conocen colectivamente como Artefactos de aliasing. Una solución a esto es hacer más búsquedas de color en la imagen de origen, para cada píxel del destino, e intentar así determinar un color más correcto para cada píxel de la imagen de destino. La solución más simple se conoce generalmente como supermuestreo o sobremuestreo. Consulta la entrada de Wikipedia sobre supermuestreo. Al tomar más muestras de la imagen de origen, sobre el área que se mapeará en cada píxel de destino, el color final de ese píxel se convertirá en una representación más precisa de la imagen distorsionada en ese punto. Cuantas más muestras de color tomes, más preciso será el color final y se generará un aspecto más suave y realista, aunque la distorsión se vuelve más lenta. Recuerda que esta técnica solo mejora realmente el aspecto general del destino en las áreas donde la imagen de origen se comprime en más del 50%. En las áreas donde la distorsión amplía la imagen de origen, o la mantiene aproximadamente a la misma escala, una única Búsqueda interpolada de la imagen de origen producirá generalmente un buen resultado con una sola búsqueda. En los ejemplos de curvado Implosionar imágenes (y muchos otros ejemplos a lo largo de los Ejemplos de IM), mencioné brevemente el método más simple de 'supermuestreo'. Básicamente, ampliar el tamaño de la imagen de salida (o en este caso simplemente ampliar la imagen de entrada) y luego realizar la distorsión. Una vez completada la distorsión, redimensionamos de nuevo la imagen a su tamaño normal, lo que fusiona todas las 'muestras' adicionales generadas. Por ejemplo...

  magick -size 94x94 xc:red -bordercolor white -border 3 \
          -virtual-pixel tile                -implode 4 \
          implode_tiled_box.gif
  magick -size 94x94 xc:red -bordercolor white -border 3 \
          -virtual-pixel tile  -resize 400%  -implode 4 -resize 25% \
          implode_tiled_ss.gif

[IM Output]
Implosión normal de una imagen de caja | [IM Output]
Implosión con supermuestreo
---|---

Por supuesto, en lugar de ampliar la imagen de entrada, podrías partir de una imagen de origen de mayor calidad (más grande), o generar una durante algún paso de procesamiento previo. Si hay una disponible. Esto es especialmente útil al rotar texto, que a menudo tiene detalles muy finos que deben preservarse de manera uniforme para asegurar un buen aspecto de alta calidad en la imagen final. Para ejemplos de esto, consulta la Transformación Polaroid. Desde IM v6.4.2-6, elOperador de distorsión general puede generar directamente una imagen de salida ampliada, que puedes escalar (o redimensionar) de nuevo para fusionar y supermuestrear los píxeles resultantes. Consulta Configuración de escala de distorsión, así como el siguiente ejemplo.
Este es solo un método de supermuestreo (conocido como el método 'grid'); sin embargo, hay muchas otras variaciones de este método. Con el tiempo, estos métodos podrían implementarse de forma más directa en ImageMagick, pero por ahora la simple ampliación y escalado de imágenes funciona bastante bien, sin necesidad de código adicional. Una última advertencia. El supermuestreo está limitado por el número de muestras que se usó para cada píxel de la imagen final y, por tanto, por la cantidad de escalado usada en el redimensionado final. Esto determina la 'calidad' final de la imagen distorsionada. Pero al usar factores de escala mayores, la imagen distorsionada será, por supuesto, mucho mucho más lenta de generar. Pero tener una calidad aún mayor tiene sus límites. En el extremo, el supermuestreo no podrá manejar ninguna distorsión de imagen que implique infinitos (como en el centro de una imagen implosionada). En tales casos se necesita una técnica completamente distinta, como la que proporciona el Remuestreo de área (consulta más abajo). En resumen, el supermuestreo puede mejorar el aspecto de imágenes con distorsiones menores, como rotaciones, cizallamientos, afines y perspectivas simples. Pero tiene límites en cuanto a los tipos de distorsiones que puede mejorar. Supermuestreo adaptativo La técnica de supermuestreo puede ampliarse aún más. En lugar de usar un número fijo de búsquedas de color para cada píxel, se realiza una comprobación, ya sea de la distancia entre las búsquedas en la imagen de origen o de cuán cercanos son los colores devueltos por un muestreo de bajo nivel, para ver si debería tomar más muestras para ese píxel concreto. Es decir, la cantidad de supermuestreo podría adaptarse a las necesidades de la distorsión, sin saber nada sobre los detalles concretos de la distorsión en sí. Esto se conoce como supermuestreo adaptativo. Esta técnica es en realidad muy común en los trazadores de rayos (ray tracers), donde es casi imposible determinar cuán compleja es la imagen resultante en un punto concreto. En este caso, a menudo se restringe al uso de 'diferencias de color' alrededor de la ubicación específica, para determinar cuándo se necesitan más muestras. Si un píxel es muy diferente de sus vecinos, entonces se usan más muestras en esa área para refinar lo que probablemente sea el borde de algún objeto tridimensional. IM no admite actualmente el supermuestreo adaptativo. Aunque es bastante posible añadir métodos de muestreo alternativos al Operador de distorsión general (consulta más abajo). Requerirá cierta reorganización funcional del código, por lo que tal vez no se añada pronto. Resumen del supermuestreo La dificultad con el supermuestreo está en determinar cuántas 'muestras puntuales' se necesitan y cómo deberían disponerse esas muestras dentro de los límites del subpíxel. También qué tipo de 'ponderación' debería aplicarse. Consulta la entrada de Wikipedia sobre supermuestreo.

Remuestreo de área, para mejores distorsiones

Una de las mejores alternativas a los métodos de supermuestreo es el remuestreo de área. En lugar de distorsionar una imagen más grande y promediar los resultados redimensionando, que es simplemente tomar y promediar más muestras de la imagen, determinamos en realidad exactamente cuántos píxeles de la imagen de origen deberían fusionarse (basándose en la 'escala' de la distorsión en ese punto) para generar cada píxel de salida concreto. Es decir, calcular un 'área' aproximada dentro de la imagen de origen que representa cada píxel de salida, y fusionar (filtrar) todos los píxeles de esa área según un filtro de remuestreo. De hecho, esto es exactamente lo que hace el Operador Resize de ImageMagick (en realidad un tipo muy específico de distorsión de imagen) para generar resultados tan buenos. No obstante, para el redimensionado solo necesitas calcular la escala del área que hay que muestrear para cada píxel una vez para toda la imagen. El área que necesita 'muestrear' es un rectángulo (ventana) de tamaño fijo en la imagen de origen, lo que hace que el proceso de remuestreo sea fácil y proporciona un atajo en el proceso de distorsión. Al remuestrear por área una imagen distorsionada, el área de píxeles (ventana) de la que tomar muestras no solo cambiará de posición, sino que también cambiará de tamaño. Como tal, un píxel del destino puede necesitar fusionar solo unos pocos colores de la imagen de origen, o incluso una sola búsqueda de color interpolada (como en las ampliaciones). Mientras que otro píxel en otra parte de la imagen de destino puede necesitar muestrear un número enorme de píxeles para generar el color final correcto. Cerca de los infinitos puede que incluso tenga que incluir todos los píxeles de la imagen de origen como parte del proceso de muestreo. Además, el área que un píxel de destino representa en la imagen de origen puede no ser un simple cuadrado, círculo o ni siquiera elipse, sino que puede ser en realidad una forma muy distorsionada, según la distorsión que se esté usando. Calcular y manejar formas tan complicadas puede ser muy costoso en tiempo, o casi imposible de lograr. [Diagram] Usar un área elíptica de la imagen de origen para calcular los colores de cada píxel de destino es un método conocido como remuestreo por media ponderada elíptica (EWA, Elliptical Weighted Average), y se expuso en el artículo de investigación en PDF "Fundamentals of Texture Mapping and Image Warping" de Paul Heckbert (que también escribió el programa 'zoom' del que se derivan prácticamente todos los algoritmos de redimensionado de imágenes). Esto se usó luego para definir el nuevo Operador de distorsión generalizado (consulta más abajo). Una elipse es la forma perfecta tanto para las Distorsiones afines como para las Distorsiones de perspectiva. Es especialmente buena para reducciones de escala extremas (consulta el ejemplo más abajo). Y aunque no es perfecta para otras distorsiones, generalmente se ajusta razonablemente a muchas otras distorsiones, como las Distorsiones de arco y polares (pero no sus inversas), así como las distorsiones radiales como la Distorsión de barril. Pero se ajusta mal a los mapeos de distorsión no lineales como De-Polar y la Distorsión de Shepard, por lo que no se usa para estas distorsiones. El supermuestreo no tiene este problema de forma, ya que cada 'muestra' se mapea de forma inversa sobre el destino. Por eso se convierte en el mejor método de muestreo en tales casos. Pero, como se mencionó, puede que no muestree todos los píxeles necesarios, o incluso que muestree demasiados píxeles.

Muestreo de área frente a supermuestreo

Aquí están los tres métodos de muestreo que IM ofrece actualmente, aplicados a una imagen en perspectiva extrema repetida infinitamente en mosaico. Consulta Mirando horizontes lejanos más abajo para ver los detalles de esta distorsión.

  # input image:  special checkerboard with a gold outline.
  magick -size 90x90 pattern:checkerboard -normalize -fill none \
          -stroke gold -strokewidth 3 -draw 'rectangle 0,0 89,89' \
          -fill red        -draw 'color 20,20 floodfill' \
          -fill lime       -draw 'color 40,70 floodfill' \
          -fill dodgerblue -draw 'color 70,40 floodfill' \
          checks.png

  # Using Interpolated Lookup
  magick checks.png -filter point \
          -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_tile_point.png

  # Using Grid Super Sampling
  magick checks.png  -filter point  -set option:distort:scale 10 \
          -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          -scale 10%    horizon_tile_super.png

  # Using Area Resampling (default)
  magick checks.png       -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_tile.png

[IM Output]
Imagen de comprobación | | [IM Output]
Búsqueda
interpolada | [IM Output]
Supermuestreo
x10 | [IM Output]
Remuestreo por área
ponderada elíptica (EWA)
---|---|---|---|---

Todas las imágenes son exactamente la misma distorsión, solo que usando diferentes técnicas de 'remuestreo'. La última imagen anterior usó la configuración EWA predeterminada del Operador de distorsión generalizado y, como puedes ver, produjo un resultado de calidad extremadamente alta. No obstante, tardó 4,6 segundos en generar esta imagen, lo cual no está nada mal aunque sea un poco lento (debido a los extremos inusuales implicados). La primera imagen tiene el remuestreo EWA predeterminado desactivado usando una configuración "[-filter](https://imagemagick.org/command-line-options/#filter) point". Esto la obliga a usar una Búsqueda interpolada directa para cada píxel. Como tal, esta imagen se generó extremadamente rápido en comparación (0,51 segundos), pero como puedes ver produce un resultado horrible a medida que la 'minificación' (submuestreo) aumenta con la 'distancia'. La imagen central es como la primera imagen, pero con la imagen de salida distorsionada ampliada por un factor de 10, antes de escalarla de nuevo (remuestreo en rejilla) para que coincida con las demás imágenes. Es decir, se buscaron y promediaron más de 100 píxeles para cada píxel de destino, a fin de Supermuestrear el resultado. Es bastante rápida de generar (1,2 segundos) y, aunque mejora la calidad de la imagen en general, esa mejora es limitada. El ×10 usado en el ejemplo anterior es muy fuerte, superando con creces el escalado más típico de 3 o 4 veces que se usa en la mayoría de los usos de supermuestreo. La mayor diferencia entre los resultados es que el supermuestreo solo realiza una mejora general de la calidad de manera uniforme en toda la imagen. A medida que la distorsión se hace más severa, empieza a fallar. El resultado son los muy visibles Artefactos de remuestreo en el plano medio y, más concretamente, una línea de efectos moaré severos justo antes del horizonte. El efecto moaré se produce cuando las 10 muestras por píxel casi coinciden con el patrón de tablero de ajedrez de la imagen, produciendo efectos de color distorsionados. Por otro lado, el remuestreo de área se concentra más en los píxeles problemáticos cercanos al horizonte (donde pasa casi todo su tiempo) que en los píxeles del primer plano, donde de hecho supera al supermuestreo. Básicamente lo anterior es una distorsión muy extrema, y el tiempo que tarda la búsqueda EWA es proporcional. Más habitualmente genera resultados mucho mejores que una sola búsqueda interpolada, ya que examina eficientemente cada píxel implicado, sin usar demasiadas muestras en áreas que no las necesitan, como sí hace el supermuestreo. En resumen... Usar una simple elipse (remuestreo EWA) o un rectángulo (Resize) para hacer 'remuestreo de área' produce buenos resultados, ya que todos los píxeles de origen implicados en distorsiones escaladas, afines o de perspectiva se fusionarán para producir el color final de un píxel de destino individual. En casos de distorsiones muy no lineales, como en las Distorsiones DePolar, o distorsiones indeterminadas, como la Distorsión de Shepard o incluso el trazado de rayos, encontrar el 'área' correcta para remuestrear todos los píxeles de origen necesarios se vuelve prohibitivo, y el supermuestreo es el mejor método para mejorar los resultados. Pero para mosaicos rectos, ampliaciones y rotaciones sin escalar, una búsqueda interpolada 'point' única y muy rápida es probablemente todo lo necesario, e incluso puede recomendarse para asegurar distorsiones no-op (sin cambios) perfectas (consulta más abajo). Recuerda, sin embargo, que todas las técnicas de remuestreo son solo métodos para determinar el color de cada píxel individual. No forma parte realmente de cómo se distorsiona una imagen, salvo en lo relativo al mapeo de ubicaciones entre el destino y el origen (o viceversa, si es posible).


Operador de distorsión generalizado

Con la generación de estos ejemplos, las discusiones derivadas en los foros de IM y las múltiples peticiones de los usuarios de formas más fáciles y rápidas de hacer perspectivas y otras distorsiones, se añadió un nuevo operador a IM v6.3.5-1 para permitirnos añadir más fácilmente distorsiones de imágenes de muchos tipos distintos. Este Operador de distorsión generalizado se llama "[-distort](https://imagemagick.org/command-line-options/#distort)", y puedes ver qué métodos de distorsión tiene disponibles en tu versión de IM usando "[-list](https://imagemagick.org/command-line-options/#list) Distort".

  magick -list distort

El operador "[-distort](https://imagemagick.org/command-line-options/#distort)" toma dos argumentos: uno de los métodos de distorsión indicados arriba, y un segundo argumento de cadena que consiste en una lista de valores en coma flotante separados por comas o espacios, que se usa para controlar el método de distorsión específico.

  magick ... -distort  {_method_}  "{_list_of_floating_point_values_}" ...

No obstante, el número de valores en coma flotante indicados depende en gran medida del método de distorsión usado, y sus significados también dependen no solo del método elegido, sino que también pueden depender del número exacto de puntos de control o atributos necesarios para un método concreto. Este es especialmente el caso de la distorsión '[Scale-Rotate-Translate](#srt)' (o '[SRT](#srt)' para abreviar), que en realidad combina tres distorsiones '[Affine](#affine)' separadas en una sola distorsión. Muchos métodos de distorsión toman una lista de puntos de control (en Coordenadas de imagen) y normalmente se indican como pares de coordenadas que controlan cómo la distorsión debe modificar la imagen. Estos pares de coordenadas se detallan más completamente más adelante en Distorsiones usando puntos de control.

Opciones, controles y configuraciones de distorsión

Marca +Distort de mejor ajuste

De forma predeterminada, "[-distort](https://imagemagick.org/command-line-options/#distort)" normalmente distorsionará la imagen o imágenes de origen en una imagen del mismo tamaño que la imagen original. Hay excepciones a esto, como la distorsión '[Arc](#arc)' (una variante de mapeo polar), donde el tamaño de la imagen de origen de entrada en realidad no tiene mucho significado en la forma distorsionada de la imagen (consulta Distorsión de arco más abajo para más detalles). La otra forma del operador, "[+distort](https://imagemagick.org/command-line-options/#distort)" (añadida en IM v6.3.5-7), intentará redimensionar la imagen distorsionada de modo que contenga la totalidad de la imagen de entrada (si es posible), de forma muy similar a lo que hacen los operadores más antiguos de Rotar y cizallar. Sin embargo, este 'modo' de operación concreto va más allá y también establece el Desplazamiento del lienzo virtual (page) de la imagen resultante. De este modo, más tarde puedes hacer un Layers Merge de esta imagen sobre otra imagen, en la posición correcta según tus puntos de control, usando la Composición alfa apropiada (consulta Cubos 3D, usando capas afines como ejemplo básico). Además (según el método de distorsión), un "[+distort](https://imagemagick.org/command-line-options/#distort)" intentará tener en cuenta cualquier Desplazamiento del lienzo virtual existente que pueda estar presente en la imagen de origen y usarlo como parte del proceso de distorsión. Consulta las notas sobre los métodos de distorsión individuales. Como tal, puede que necesites hacer un uso juicioso del operador de configuración de atributos "[+repage](https://imagemagick.org/command-line-options/#repage)" para borrar o ajustar ese desplazamiento antes de usar la forma de 'mejor ajuste' "[+distort](https://imagemagick.org/command-line-options/#distort)" del operador de distorsión general. También puede que necesites usarlo después si el lienzo virtual y el desplazamiento no son necesarios. Consulta también Eliminar geometría de lienzo/página. El "[-distort](https://imagemagick.org/command-line-options/#distort)" normal simplemente ignorará cualquier desplazamiento existente presente en la imagen de origen en lo que respecta a la distorsión en sí, pero copiará ese desplazamiento sin cambios a la imagen distorsionada. En resumen... Usa "[-distort](https://imagemagick.org/command-line-options/#distort)" para que los resultados se mapeen en una imagen del mismo tamaño. Y usa "[+distort](https://imagemagick.org/command-line-options/#distort)" para intentar establecer automáticamente el tamaño de la imagen de salida, PERO también para usar y generar desplazamientos del lienzo virtual (atributos de página). Consulta también Viewport de distorsión (más abajo) si quieres anular esta selección general de viewport y controlar exactamente qué tamaño y qué parte de la imagen distorsionada quieres ver en tus resultados.
Nota... El viewport de mejor ajuste generado por "[+distort](https://imagemagick.org/command-line-options/#distort)" es 2 píxeles más grande de lo que los usuarios normalmente esperarían. La razón es que estos píxeles contienen píxeles semitransparentes que resultan del filtro de remuestreo de área, y estos píxeles son vitales para una 'unión de bordes' y superposición correctas de la imagen distorsionada. Técnicamente, el número de píxeles añadidos debería depender del escalado de salida del Soporte del filtro de remuestreo. Es decir, cuánto podría 'extenderse' el área de un píxel debido al filtro de remuestreo. No obstante, como el escalado de cada píxel puede ser variable, calcular el número absolutamente correcto de píxeles adicionales necesarios es un asunto muy delicado y normalmente no merece la pena. Por tanto, los 2 píxeles añadidos son un 'apaño', ya que las distorsiones rara vez amplían imágenes, lo que hace que los píxeles se 'extiendan' más. Además, como la mayoría de los filtros de remuestreo estándar tienen un soporte de 2 unidades, añadir 2 píxeles es razonable. Y como esta adición es 'fija', permite a los usuarios la opción de simplemente Recortar el tamaño de la imagen (de varias formas), si así lo desean. El 'apaño' de 2 píxeles sí se vuelve obviamente demasiado pequeño al hacer ampliaciones de imágenes. Pero esas son distorsiones bastante raras, y los usuarios pueden definir su propio Viewport (consulta más abajo) si esto supone un problema. El desplazamiento virtual de la imagen distorsionada sobre el lienzo virtual se ajusta para tener en cuenta estos 2 píxeles adicionales, de modo que la imagen distorsionada es correcta para la superposición, aunque no para la composición simple. Pero ten en cuenta que, si bien Crop y Trim preservarán la ubicación de la imagen en capa, Shave y Chop desplazarán la imagen de la capa respecto a este desplazamiento.

Determinación del color de píxel en Distort

Como se explicó arriba en Mapeo inverso de píxeles, cada punto de la imagen resultante se determina mapeando primero la ubicación de ese píxel en la imagen de destino a la ubicación equivalente (distorsionada de forma inversa) en la imagen de origen, según el método de distorsión elegido. No obstante, el color final del píxel no es tan sencillo de determinar, ya que se ve afectado por un gran número de factores.

Píxeles virtuales y mosaicos

El punto mapeado por la distorsión puede no caer en la imagen de origen real, sino en algún lugar al lado, o incluso muy lejos de la imagen real. La solución a esto es fingir que la imagen de origen está rodeada por una superficie 'infinita' o 'virtual', que se define mediante la configuración "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" actual. Para más detalles y ejemplos del efecto de esta configuración, consulta los ejemplos de Píxel virtual. Esto puede ser muy útil para generar patrones de mosaico distorsionados, o incluso no distorsionados, de la imagen de origen. Las técnicas para esto se muestran en la propia sección de Píxel virtual (no distorsionados) y en Mosaico afín y Mirando horizontes lejanos más abajo.

Píxeles de distorsión inválidos

¡A veces la distorsión de un píxel de destino ni siquiera 'alcanza' la imagen virtual repetida en mosaico! Esto suele ocurrir cuando distorsionas la imagen usando algún tipo de método de distorsión de espacio tridimensional y el 'vector' del píxel ni siquiera alcanza el plano de origen en el que yace la imagen. Básicamente, el resultado de la distorsión se vuelve matemáticamente 'indefinido'. En ese caso, el color se determinará a partir de la configuración "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)". Por ejemplo, cuando ves 'cielo' en una Distorsión de perspectiva (por ejemplo, consulta Mirando horizontes lejanos), las matemáticas para determinar la ubicación de la imagen de origen quedaron 'indefinidas' (en realidad está definida, pero no es válida desde la perspectiva de visión directa del usuario). Como tal, el "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" se emite para el 'cielo'. En realidad, el algoritmo de distorsión de perspectiva también consigue incluir algo de información de 'anti-aliasing' para los píxeles cercanos al horizonte, aunque eso es poco común en tales situaciones.

Remuestreo EWA y filtros

Una vez que sabes dónde 'alcanza' un píxel de destino la imagen de origen, necesitas determinar el color del píxel de destino usando los píxeles cercanos al punto de 'impacto' en la imagen de origen. Normalmente, el Operador Distort usará el método de Remuestreo de área EWA (Elliptical Weighted Average, media ponderada elíptica) para promediar un área mayor de la imagen de origen y obtener el color correcto de este píxel. Puedes cambiar el filtro que usa el remuestreo EWA mediante la configuración "[-filter](https://imagemagick.org/command-line-options/#resize)". Consulta Filtros de remuestreo y, más concretamente, Filtros cilíndricos para más detalles. Originalmente se usaba un filtro Gaussiano cilíndrico para el remuestreo EWA, ya que esto era lo que se definía en el artículo de investigación original sobre remuestreo EWA. Pero este tiende a producir un resultado muy borroso, aunque tampoco produce efectos de aliasing. Este solía ser el filtro predeterminado, junto con un error de implementación que causaba una borrosidad extrema antes de esa versión (ahora corregido). Desde IM v6.6.5-0, tras grandes discusiones con Nicolas Robidoux, profesor de Matemáticas en la Universidad Laurentian, el filtro predeterminado para las distorsiones de imagen se reemplazó por el filtro '**Robidoux**', que es un filtro cúbico muy 'tipo Mitchell', diseñado específicamente para el remuestreo EWA. Consulta Filtros cilíndricos para información sobre este y otros filtros cilíndricos. No obstante, ten en cuenta que cualquier función de filtro Sinc con ventana subyacente se reemplaza por la función de filtro Jinc con ventana, más circular. Como tal, seleccionar un filtro 'Lanczos' devolverá un filtro "Jinc con ventana Jinc", en lugar de un filtro "Sinc con ventana Sinc". Consulta Filtros cilíndricos Jinc con ventana para más detalles. NOTA AL MARGEN: las funciones 'Sinc' NO son realmente utilizables como función cilíndrica, ya que la interacción de la función con las distancias radiales en una rejilla hace que los pesos del filtro adopten una forma que tiende a anularse a sí misma (suma de pesos cero) siempre que se usa un número par de 'lóbulos'. Esto, a su vez, hace que intente generar colores casi infinitos cuando se usa con un patrón 'hash' de tablero de ajedrez a nivel de píxel. Básicamente, EWA usa filtros de remuestreo, de forma muy parecida al Operador Resize y, como tal, también puedes modificar los filtros usando las especiales Opciones de filtro avanzadas. La borrosidad de un filtro 'Gaussian' y de filtros tipo gaussiano, por ejemplo, puede controlarse mediante la Configuración de desenfoque del filtro. De manera similar, puedes usar la Configuración de soporte por lóbulos para controlar el tamaño y la potencia de los filtros Jinc con ventana, como un filtro 'Lanczos'. | _Hay una serie de métodos de distorsión extrema que desactivan automáticamente el remuestreo EWA y solo usan laBúsqueda interpolada más directa.

Por ejemplo, la distorsión Depolar produce áreas de remuestreo con forma de arcos circulares que no se ajustan muy bien al remuestreo 'elíptico' (EWA). Otras distorsiones, como Shepards, hacen que el cálculo de los 'factores de escala' sea extremadamente difícil, aunque una futura mejora del operador distort podría hacerlo posible).

Se recomienda una técnica de Supermuestreo para estos métodos de distorsión a fin de evitar generar Artefactos de aliasing severos en áreas de compresión de imagen (submuestreo) en los resultados.

_
---|---

Fallo de remuestreo

En algunas situaciones especiales, la elipse de remuestreo EWA puede no llegar a 'alcanzar' ningún píxel real con el que crear una media ponderada. Básicamente, la elipse es tan pequeña, o tan delgada, que cae completamente entre todos los píxeles de la imagen. Y sin ningún color de píxel, no puede generar un color para la imagen de salida en ese punto. Esta es una situación extrema y, por lo general, es imposible de lograr a menos que estés jugando con las Configuraciones de filtro avanzadas. Pero en el improbable caso de que no se alcance ningún píxel, o de que los pesos del filtro sumen cero, el remuestreo fallará. En ese caso, IM recurrirá a usar una simple búsqueda interpolada directa, igual que la que obtendrías si desactivas el filtrado EWA (consulta el siguiente apartado). Si quieres comprobar si esto está ocurriendo, puedes usar la especial Interpolación de fondo con un color de fondo inusual (como 'red') para resaltar cualquier fallo de remuestreo de este tipo. Por ejemplo, aquí establezco deliberadamente el soporte de un filtro box demasiado pequeño, haciendo así que la elipse de remuestreo sea muy pequeña. También amplío mucho la imagen para que puedas ver qué partes 'alcanzaron un píxel' y cuáles no. |

  magick \( xc:red   xc:white xc:black +append \) \
          \( xc:blue  xc:lime  xc:white +append \) \
          \( xc:black xc:red   xc:blue  +append \) -append \
          -filter Box -define filter:support=0.4 \
          +distort SRT 30,0  bad_box_distort.png

[IM Output]
En la imagen muy ampliada, el círculo de remuestreo o bien alcanzará solo un píxel (produciendo un círculo aliasado de color sólido), o bien no logrará coincidir con ningún píxel porque el área de muestreo circular cae completamente entre los píxeles y, por tanto, el filtro recurrirá a un degradado de color interpolado (Interpolación bilineal por defecto) para obtener al menos algún color razonablemente válido para la imagen resultante. Aquí está el mismo ejemplo, pero reemplazando el método de interpolación con la especial (y normalmente inútil) Interpolación de fondo (simplemente devuelve el color de fondo, que se estableció en 'gray'). |

  magick \( xc:red   xc:white xc:black +append \) \
          \( xc:blue  xc:lime  xc:white +append \) \
          \( xc:black xc:red   xc:blue  +append \) -append \
          -filter Box -define filter:support=0.4 \
          -interpolate background -background Gray \
          +distort SRT 30,0   bad_box_distort_gray.png

[IM Output]
Para una cobertura completa (de modo que siempre encuentre al menos un píxel), un filtro de remuestreo cilíndrico necesita un 'soporte' de al menos unos 0,707 (sqrt(2)/2) (predeterminado para un filtro box). Todos los filtros son normalmente mucho mayores que este tamaño de soporte mínimo. Para ejemplos de esto, consulta la sección sobre Filtros cilíndricos. | _Los pequeños puntos de color en las esquinas se deben a una optimización del remuestreo para píxeles virtuales (abortar un costoso remuestreo EWA al muestrear áreas de VP de color sólido). Desaparecerán o cambiarán con una selección distinta de la configuración "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)".

Normalmente esto no es un problema, y solo se ve aquí porque distort usa un 'Viewport de mejor ajuste' ligeramente mayor que la imagen original y, por tanto, incluye unos pocos píxeles adicionales alrededor del borde que en este caso muestrean el píxel virtual.

_
---|---

Búsqueda de color interpolada o directa

Puedes usar "[-filter](https://imagemagick.org/command-line-options/#filter) point" para desactivar el filtrado y, por tanto, el remuestreo EWA.Cuando se hace esto, ImageMagick cambiará las búsquedas de color para usar la Interpolación de píxeles, rápida y más simple. Es decir, buscará un color usando solo una referencia de 'punto único' a la imagen de origen, sin ningún 'área de remuestreo'. El color de los píxeles resultantes usará un color interpolado basado únicamente en los vecinos más cercanos al punto.

La interpolación generalmente causará efectos de aliasing severos
cuando se produzca cualquier forma de minificación o submuestreo de la imagen.

Pero funciona extremadamente bien para imágenes que contienen distorsiones mínimas, como rotaciones, mosaicos, o para la ampliación de imágenes (magnificación o sobremuestreo). Una técnica de Supermuestreo puede combinarse con la interpolación para mejorar los resultados en áreas de fuerte compresión, minificación o submuestreo. Consulta Problemas del ciclo Depolar-Polar (una distorsión que no puede usar remuestreo EWA) para un ejemplo de uso del supermuestreo para resolver el aliasing por interpolación.

Resumen detallado de la distorsión

Al establecer "[-verbose](https://imagemagick.org/command-line-options/#verbose)" antes de ejecutar "[-distort](https://imagemagick.org/command-line-options/#distort)" (usa "[+verbose](https://imagemagick.org/command-line-options/#verbose)" para volver a desactivarlo), distort emitirá al canal de error estándar información sobre el algoritmo y los coeficientes internos que calcula, y usa al distorsionar la imagen dada, de la forma especificada. Puedes usar esta información para examinar y entender cómo funciona y se aplica la distorsión. También es una herramienta de depuración que podemos usar para averiguar qué está fallando, y como parte del proceso de implementación de nuevas distorsiones.

  magick koala.gif -verbose -distort SRT 0 +verbose  koala_noop.gif

[IM Output] | | | [IM Text]

| [IM Output]

| NOTA: La imagen resultante es casi, pero no exactamente, igual que la imagen de entrada (consulta "distorsiones no-op" a continuación).
---|---
La salida detallada describe las dos técnicas alternativas de distorsión para la distorsión dada. Una es una distorsión '[AffineProjection](#affineprojection)', mientras que la otra muestra una alternativa con el Operador FX DIY que detalla exactamente cómo mapea un píxel dado de la imagen de salida (i,j) a una búsqueda interpolada en la imagen de entrada (xx,yy), para transformar la imagen así. Realiza el cálculo de la elipse de remuestreo, que usa matemáticas complejas (valores propios) para averiguarla; solo calcula el punto de búsqueda interpolada sin escalar en la imagen de origen a partir del cual determinar el color del píxel (i,j). Ambas dan información sobre el proceso de distorsión y pueden usarse para extraer información extra para usar en otras distorsiones del mismo tipo. Para un ejemplo más complejo del uso de esta información, consulta Interioridades de la perspectiva e Interioridades del bilineal más abajo. Y para un ejemplo del uso de un comando FX para la distorsión de imágenes, consulta Redimensionado de imágenes con FX. Las sumas y restas adicionales de '0.5' en lo anterior son necesarias para convertir 'coordenadas de píxel' en 'coordenadas de imagen', y se requieren para el manejo matemático correcto de las distorsiones de imagen. Consulta Coordenadas de imagen frente a de píxel más abajo.

Distorsiones no-op

El ejemplo anterior muestra los resultados de hacer una distorsión no-op. Es decir, pasar una imagen por distort (para algún efecto secundario) pero sin ninguna distorsión real implicada (solo un mapeo 1 a 1 de píxeles). El filtro de remuestreo EWA no reproducirá exactamente los mismos colores que el original, sino que desenfocará muy ligeramente los píxeles individuales con sus vecinos. Esto se debe al filtro bidimensional que se usa y, aunque el desenfoque de color es mínimo, nunca puede eliminarse. Como tal, para hacer un verdadero 'no-op', también debemos desactivar el filtrado EWA y usar la Búsqueda de color interpolada o directa (consulta arriba). |

  magick koala.gif -filter point -distort SRT 0  koala_noop_perfect.gif

[IM Output]
Casi todas las Configuraciones de interpolación extraerán generalmente una copia exacta del píxel de origen cuando se referencia exactamente. No obstante, como precaución, también puedes especificar la interpolación Nearest-Neighbor, por velocidad y garantía de que solo se devuelve una coincidencia exacta de color, independientemente de cualquier error de coma flotante que distort pueda producir. |

  magick koala.gif   -filter point  -interpolate nearest \
          -distort SRT 0  koala_noop_perfect_2.gif

[IM Output]
Esto puede parecer contraproducente, pero puede ser un método muy útil para ampliar el área de una imagen, o para repetir imágenes en mosaico (usando Métodos de píxel virtual), sin redimensionar realmente los datos de la imagen original. Consulta Mosaico usando píxeles virtuales mediante Distort para ejemplos de esto. Es decir, usar el Operador Distort por sus efectos secundarios, como el mosaico de píxeles virtuales multi-imagen, la ampliación o el recorte del tamaño de la imagen, la adición de bordes, o incluso la traslación (en cantidades enteras o incluso sub-pixel). Nada de lo cual requiere realmente que la imagen se 'distorsione', solo que se 'modifique' de alguna forma 'programada'.

Viewport, dónde mira Distort

Como se mencionó arriba, usar "[-distort](https://imagemagick.org/command-line-options/#distort)" o "[+distort](https://imagemagick.org/command-line-options/#distort)" cambia el tamaño y la ubicación resultantes de la 'imagen de destino' para que sean, respectivamente: iguales a la imagen de origen (ignorando cualquier configuración del lienzo virtual), o un cálculo de mejor ajuste para la imagen de origen distorsionada (si es posible). Estas dos cosas básicamente definen qué parte del 'espacio distorsionado' resultante está viendo la imagen de destino. Otra forma de pensarlo es que la imagen de destino es una 'ventana' que mira la imagen distorsionada resultante, o un 'viewport' hacia el espacio distorsionado. La configuración "distort:viewport" anula ambos valores predeterminados y te permite especificar directamente qué parte del espacio distorsionado quieres ver...

[-define](https://imagemagick.org/command-line-options/#define) distort:viewport=WxH+X+Y
[-set](https://imagemagick.org/command-line-options/#set) option:distort:viewport WxH+X+Y

Estas se añadieron en IM v6.3.6-1. No amplía ni escala la imagen distorsionada, solo especifica la ubicación y el área que se está viendo (el viewport) en el espacio de la imagen distorsionada. Esto puede usarse para crear una imagen de destino de un tamaño específico, o para desplazar la vista a un área concreta en el espacio de la imagen distorsionada. Es muy similar a usar 'Recorte de viewport' de una imagen distorsionada de tamaño infinito (definida por píxeles virtuales). Por ejemplo, aquí recortamos la salida para que solo muestre la cabeza del koala (con una distorsión no-op). En otras palabras, solo un 'recorte de viewport' directo de la imagen original no distorsionada. |

  magick koala.gif  -define distort:viewport=44x44+15+0 \
          -filter point -distort SRT 0  +repage koala_viewport.gif

[IM Output]
Y aquí expandimos la vista para mirar el espacio extra que rodea la imagen distorsionada, mostrando los efectos que la configuración de Píxel virtual tiene sobre el espacio infinito que rodea la imagen de origen original. |

  magick koala.gif  -define distort:viewport=125x125-25-25 \
          -filter point -distort SRT 0  +repage koala_viewport_2.gif

[IM Output]
En este caso se parece más a usar el Operador Extent para ampliar la imagen. Sin embargo, en lugar de rellenar simplemente con el color de fondo, distort rellena el área añadida con la Configuración de píxel virtual. En este caso usando la configuración de píxel virtual '[Edge](misc.html#edge)' predeterminada, lo que da como resultado las líneas horizontales y verticales de píxeles, replicadas a partir de los píxeles del borde de la imagen original. Puede que te interese elegir una mejor opción para la Configuración de píxel virtual. Por ejemplo, usar una configuración '[Background](misc.html#background)' hará que esta distorsión no-op funcione prácticamente igual que el Operador Extent. Para esta imagen, una configuración de píxel virtual '[White](misc.html#white)' sería probablemente una mejor elección. |

  magick koala.gif  -define distort:viewport=125x125-25-25 \
          -virtual-pixel White -distort SRT 0  +repage koala_viewport_3.gif

[IM Output]
El "[+repage](https://imagemagick.org/command-line-options/#repage)" final en los ejemplos anteriores es necesario para eliminar el desplazamiento del lienzo virtual del viewport que "[-distort](https://imagemagick.org/command-line-options/#distort)" dejará puesto cuando se usa la configuración de viewport. Esta información simplemente no se desea en este caso. En otros casos, como al superponer imágenes distorsionadas, sí querrías esa información de desplazamiento. La opción de viewport es especialmente útil con una configuración de píxel virtual '[Tile](misc.html#tile)', o incluso '[Mirror](misc.html#mirror)', que te permite generar imágenes en mosaico de cualquier tamaño y en distintos estilos. Incluso puedes usar distort para distorsionar esas imágenes en mosaico, como se ejemplifica en Mosaico afín más abajo. |

  magick koala.gif  -define distort:viewport=125x125-25-25 \
          -virtual-pixel Mirror -distort SRT 0  +repage koala_viewport_4.gif

[IM Output]

Recorte cuadrado centrado

Si usas la opción "[-set](https://imagemagick.org/command-line-options/#set)" para establecer el 'viewport' de la imagen resultante, puedes incluir Secuencias de escape de porcentaje en el valor asignado. Más concretamente, puedes incluir Secuencias de escape de porcentaje FX que pueden hacer cálculos matemáticos. Esto significa que el 'viewport' puede calcularse, haciendo uso de los atributos como, por ejemplo, el tamaño de la imagen actual en memoria, para especificar el tamaño final de la imagen resultante. ¿Qué significa eso? Bueno, significa que el 'viewport' puede usarse para generar tipos especiales de Recorte que normalmente requieren una o más lecturas previas de una imagen (o una interfaz de programación de API más avanzada) y cálculos externos para lograrlo. Por ejemplo, puedes recortar un 'cuadrado central' de una imagen sin necesidad de conocer de antemano el tamaño o la orientación de la imagen original. Esto es complejo, así que coloqué la expresión del viewport en variables para que sea más fácil de leer, codificar y depurar, aunque en realidad es solo una expresión constante (fija).

  size='%[fx: w>h ? h : w ]'
  offset_x='%[fx: w>h ? (w-h)/2 : 0 ]'
  offset_y='%[fx: w>h ? 0 : (h-w)/2 ]'
  viewport="${size}x${size}+${offset_x}+${offset_y}"

  magick worldmap_sm.jpg  -set option:distort:viewport "$viewport" \
          -filter point -distort SRT 0  +repage   viewport_square.gif

[IM Output] [IM Output]

La imagen resultante es el mayor cuadrado centrado que puede extraerse de cualquier imagen de origen de entrada, independientemente del tamaño de esa imagen. El propio distort no distorsiona realmente la imagen, solo copia el área cubierta por el viewport. Ten en cuenta que es necesario calcular los CUATRO números para producir un "recorte cuadrado centrado", ya que todos los valores dependen de la orientación de la imagen. Como tal, cada expresión usa una prueba de 'orientación de imagen' de la forma 'w>h ? ... : ...', de modo que el valor resultante depende de la orientación de la imagen. Esta es una forma alternativa usando las funciones "min()" y "max()", en lugar de pruebas de orientación de imagen. |

  magick worldmap_sm.jpg  -set option:distort:viewport \
    "%[fx:min(w,h)]x%[fx:min(w,h)]+%[fx:max((w-h)/2,0)]+%[fx:max((h-w)/2,0)]" \
    -filter point -distort SRT 0  +repage  viewport_square_2.gif

[IM Output]
Cortesía de la página Tidbits de Fred Weinhaus. En Miniaturas, relleno cuadrado y recorte se muestra una técnica que usa múltiples técnicas de procesamiento de imágenes para hacer lo mismo.

Recorte por relación de aspecto

Esta técnica puede ampliarse para que recortes una imagen de forma centrada y se ajuste a una relación de aspecto dada. Consulta también la discusión del foro Recortar a relación de aspecto.

Otros ejemplos de viewport

Consulta también Métodos para rotar imágenes más abajo para otros ejemplos de uso de un viewport para controlar qué parte del espacio distorsionado es visible en los resultados.

Escalado de salida y supermuestreo

[-define](https://imagemagick.org/command-line-options/#define) distort:scale=N
[-set](https://imagemagick.org/command-line-options/#set) option:distort:scale N

Se añadió en IM v6.4.2-6 como un factor general de escalado de la imagen de salida. Esto amplía la imagen de salida por el factor dado y, por tanto, "[-distort](https://imagemagick.org/command-line-options/#distort)" necesitará generar N2 'muestras' de búsqueda distorsionada adicionales. El número suele ser un entero, pero puede ser un factor de ampliación en coma flotante. Ten en cuenta que muchas distorsiones también te permiten 'escalar' el tamaño de la imagen distorsionada resultante; sin embargo, el tamaño de la imagen resultante no se vería afectado por ese escalado (a menos que se usara un "[+distort](https://imagemagick.org/command-line-options/#distort)" de 'mejor ajuste'). No obstante, esta configuración 'scale' no cambia en absoluto el contenido de la imagen resultante, solo amplía o reduce la imagen de salida resultante. Esto puede usarse, por ejemplo, con un 'viewport' apropiado para producir una imagen que puedas "[-resize](https://imagemagick.org/command-line-options/#resize)" fácilmente a un tamaño específico, lo que te permite generar un 'zoom' controlado en la imagen distorsionada, sin pérdida de calidad. Por ejemplo, hacemos 'zoom' sobre la cabeza del koala. |

  magick koala.gif -set option:distort:scale 2.5 \
          -set option:distort:viewport 44x44+15+0 \
          -distort SRT 0  +repage koala_zoom.gif

[IM Output]
Ten en cuenta que, aunque se solicitó que el viewport fuera de 44x44 píxeles, la imagen de salida real se ha escalado a 110x110 píxeles. Más habitualmente, se usa como un medio sencillo de 'Supermuestreo' (consulta arriba) de la operación de distorsión. Para esto se usa un factor de escala de 'supermuestreo' entero y, tras distorsionar, la imagen se escala de nuevo a su tamaño original, para fusionar las muestras adicionales y producir un resultado de mayor calidad. |

  magick koala.gif -filter point -set option:distort:scale 10 \
          -distort SRT 0  -scale 10%   koala_super.gif

[IM Output]
Además, como el 'Remuestreo de área' no es necesario al usar 'Supermuestreo' para mejorar la calidad de la imagen (solo lo ralentiza), normalmente se desactiva usando una opción "[-filter](https://imagemagick.org/command-line-options/#filter) point" (consulta la sección anterior).


Introducción a los métodos de distorsión

Distorsión Scale-Rotate-Translate (SRT)

Una de las distorsiones más simples, pero probablemente una de las más versátiles, es la distorsión 'SRT o 'Scale-Rotate-Translate'. (SRT es solo una abreviatura rápida) Ya has visto el ejemplo 'no-op' de esta distorsión en los ejemplos anteriores, donde la imagen se procesa sin aplicarle ninguna distorsión real, aunque seguirá filtrándose, lo que puede inducir un desenfoque muy leve. Aquí repetimos los resultados del 'no-op' distort anterior...

  magick koala.gif    -distort SRT 0    koala_noop.gif

[IM Output] [IM Output]

| _Tenga en cuenta que la imagen se difuminará muy ligeramente como consecuencia de usar elremuestreo por áreas. No obstante, los filtros de remuestreo de IM se han diseñado deliberadamente para minimizar este difuminado en la distorsión sin efecto, lo cual es necesario para el uso normal.

Si quiere una distorsión 'sin efecto' perfecta para fines especiales, desactive el remuestreo EWA. Es decir, especifique el filtro 'sin efecto' "-filter Point" en el ejemplo anterior antes del operador de distorsión.


---|---
La distorsión 'SRT' son en realidad tres distorsiones separadas dentro de un único método de distorsión, razón por la cual se denomina distorsión 'Scale-Rotate-Translate' (escalar-rotar-trasladar). Todos los argumentos, salvo la rotación del _ángulo
, son opcionales, lo que hace que los argumentos sean muy variables según cuántos argumentos separados por comas o espacios proporcione, hasta un máximo de 7 números en coma flotante. **-distort SRT "** |

                  Angle

| **"** | -> rotación centrada
---|---|---|---

        Scale     Angle

| -> escalado y rotación centrados

X,Y               Angle

| -> rotación alrededor de una coordenada dada

X,Y     Scale     Angle

| -> escalado y rotación alrededor de una coordenada

X,Y ScaleX,ScaleY Angle

| -> ídem

X,Y     Scale     Angle  NewX,NewY

| -> escalar, rotar y trasladar la coordenada

X,Y ScaleX,ScaleY Angle  NewX,NewY

| -> ídem
Lo que esto hace es tomar una imagen en la que ha seleccionado, y un punto de control opcional. Si no se da ningún punto de control, se usa el centro exacto de la imagen de origen de entrada. Alrededor de ese punto, la distorsión, en secuencia... Escala la imagen, la Rota y luego Traslada o mueve el punto de control seleccionado a una nueva posición. De ahí el nombre de esta distorsión. El orden de los argumentos mostrado arriba refleja el orden de las operaciones que realmente se aplican a la imagen. X,Y para trasladar el 'centro' de las transformaciones al origen, ScaleX,ScaleY para escalar la imagen, Angle para rotar la imagen, y luego NewX,NewY para trasladar el 'centro' a estas coordenadas. Es decir, el operador representa en realidad 4 operaciones internas de distorsión aplicadas todas simultáneamente como una única distorsión. Aunque para nosotros, los humanos, solo intervienen 3 distorsiones distintas. Veamos un ejemplo sencillo usando la imagen 'koala'... Un solo argumento es simplemente una rotación sencilla alrededor del centro de la imagen, que produce básicamente un resultado similar al del antiguo operador Rotate, pero sin ningún aumento del tamaño de la imagen. |

  magick koala.gif  -background skyblue  -virtual-pixel background \
          -distort ScaleRotateTranslate -110 koala_srt_rotate.png

[IM Output]
Tenga en cuenta que, de forma predeterminada, el tamaño de la imagen de entrada se usa también para la imagen de salida, por lo que la imagen rotada puede quedar recortada. También queda perfectamente centrada, independientemente de si la imagen tiene un número par o impar de píxeles. Usando la forma 'plus' de "+distort", y una limpieza de los desplazamientos del lienzo virtual resultante, podemos generar algo muy parecido al operador Rotate normal. |

  magick koala.gif  -background skyblue  -virtual-pixel background \
          +distort ScaleRotateTranslate -110 +repage koala_srt_rotate2.png

[IM Output]
| A partir de IM 6.7.3-4 eloperador Rotate usa ahora la distorsión SRT. Antes de esto usaba operaciones de cizallamiento, que no producían un resultado tan bueno.
---|---
Reduzcámosla también un 30 %, pero usando un fondo transparente. |

  magick koala.gif  -alpha set -virtual-pixel transparent \
          +distort ScaleRotateTranslate '.7,-110' +repage koala_srt_scale.png

[IM Output]
El siguiente conjunto de argumentos especificará el 'centro' alrededor del cual se rota y escala la imagen. Este punto se denomina 'punto de control' o 'manejador' en la imagen, que es una ubicación usada para controlar la distorsión. Como estamos usando un punto específico para esta distorsión, no usemos el modo de 'mejor ajuste' para evitar las complicaciones de los 'desplazamientos virtuales'. Por ejemplo, rotemos y escalemos el koala alrededor de su 'nariz', que está ubicada en 28,24 en la imagen de origen. Ya que estamos, distorsionemos las escalas X e Y de forma distinta. |

  magick koala.gif  -background skyblue -virtual-pixel background \
          -distort ScaleRotateTranslate '28,24  .4,.8  -110' \
          koala_srt_center.png

[IM Output]
Y como ejemplo final, movamos también la 'nariz' cerca de la parte inferior de la imagen, y fijemos el fondo a un fondo blanco a juego. |

  magick koala.gif  -virtual-pixel white \
          -distort ScaleRotateTranslate '28,24  .4,.8  -110  37.5,60' \
          koala_srt_trans.png

[IM Output]
Tenga en cuenta que la posición final también es un valor en coma flotante. De hecho, todos los argumentos pueden ser valores en coma flotante y la distorsión hará lo correcto. Recuerde que cada una de las operaciones —escalar, rotar y trasladar— se realiza en ese orden. Como puede ver, esta distorsión es muy versátil, y aunque puede pensar en ella como una distorsión de la imagen mediante tres métodos diferentes en secuencia, en realidad aplica las tres distorsiones simultáneamente para producir el resultado mostrado. Esto la hace más rápida que aplicar varios operadores individuales, y generalmente produce un mejor resultado final. Lo anterior también muestra el uso de diferentes ajustes de píxel virtual para definir el color usado en las áreas referenciadas fuera de la imagen de origen real. Para ver el efecto de la interpolación en las rotaciones, consulte Interpolación de una línea y un borde rotados. Esta distorsión está diseñada específicamente para tomar una imagen y generar una animación basada en los movimientos y la rotación de ese objeto. Por ejemplo, aquí creo una nave espacial estilizada, que luego animo de manera muy tosca. La nave se asienta sobre su base en 20,75 (para el escalado inicial de 'agacharse'), mientras que el 'manejador' normal para el movimiento y las rotaciones es el centro de la nave, ubicado en 20,60 en la imagen original. Estos puntos representan puntos de control mediante los cuales el objeto puede entonces animarse en términos sencillos.

  magick -size 80x80 xc:skyblue -fill yellow -stroke black \
          -draw 'path "M 15,75 20,45 25,75 Z  M 10,55 30,55" ' \
          spaceship.gif
  magick spaceship.gif \
          \( -clone 0  -distort SRT '20,75  1.0,0.6  0' \) \
          \( -clone 0  -distort SRT '20,60     1     0  20,49' \) \
          \( -clone 0  -distort SRT '20,60    0.9   20  27,35' \) \
          \( -clone 0  -distort SRT '20,60    0.8   45  40,23' \) \
          \( -clone 0  -distort SRT '20,60    0.5   70  55,15' \) \
          \( -clone 0  -distort SRT '20,60    0.3   75  72,11' \) \
          \( -clone 0  -distort SRT '20,60    0.1   80  100,8' \) \
          -set delay 50  -loop 0  spaceship_launch.gif

[IM Output] [IM Output]

Por supuesto, es un ejemplo muy tosco de cómo se puede usar una distorsión '[SRT](#srt)' para animar una imagen estática, pero le da la idea. Puede añadir más fotogramas, y quizá algo de fuego y humo, para mejorarlo aún más (se aceptan envíos y el mejor resultado se añadirá aquí con su nombre).

Métodos para rotar imágenes

Las imágenes se pueden rotar de muchas maneras. Pero puede que las rotaciones simples no sean lo que busca. Rotar la imagen sin cambiar el tamaño... |

  magick rose: -virtual-pixel black -distort SRT '20'  rotate_normal.png

[IM Output]
O rotar de modo que no se recorte nada de la imagen rotada... |

  magick rose: -virtual-pixel black +distort SRT '20'  rotate_noclip.png

[IM Output]
Sin embargo, lo habitual es no querer ver el píxel virtual 'negro' (o cualquier otro color que no sea de la imagen) que rodea la imagen propiamente dicha. Una solución es recortar la imagen (usando un ajuste de viewport de distorsión) al mayor rectángulo de la misma relación de aspecto, de modo que solo contenga píxeles reales de la imagen resultantes de la rotación. No obstante, calcular este rectángulo es bastante complicado, y se discutió ampliamente en el foro de ImageMagick usando unas ecuaciones encontradas en el Math Help Forum. Aquí rotamos y hacemos un recorte interno tan cercano a la relación de aspecto original como sea posible. |

  angle=20
  ratio=`magick rose: -format \
     "%[fx:aa=$angle*pi/180; min(w,h)/(w*abs(sin(aa))+h*abs(cos(aa)))]" \
     info:`
  crop="%[fx:floor(w*$ratio)]x%[fx:floor(h*$ratio)]"
  crop="$crop+%[fx:ceil((w-w*$ratio)/2)]+%[fx:ceil((h-h*$ratio)/2)]"
  magick rose: -set option:distort:viewport "$crop" \
          +distort SRT $angle +repage   rotate_internal.png

[IM Output]
Esto parece complejo, pero se debe a que en realidad tiene que calcular 4 valores separados para definir el ajuste de viewport: anchura, altura y desplazamiento en la imagen original. Otra alternativa es no solo rotar, sino también escalar la imagen ligeramente más grande para que 'llene' los límites de la imagen original. |

  angle=20
  magick rose: -distort SRT \
     "%[fx:aa=$angle*pi/180;(w*abs(sin(aa))+h*abs(cos(aa)))/min(w,h)], $angle" \
     rotate_correction.png

[IM Output]
Esta última opción es ideal para una corrección de rotación menor de fotos, de modo que se preserve el tamaño original de la imagen. La única razón por la que este método es más simple es porque solo hay que calcular un valor de 'escala', y por tanto puede hacerse 'en línea'.

Distorsiones mediante puntos de control

Mientras que el método de distorsión '[SRT](#srt)' se define especificando ángulos de rotación y factores de escala, la mayoría de las distorsiones se definen moviendo 'puntos' en la imagen de origen, y trasladándolos a una nueva posición en la imagen resultante. Esto es un poco como el movimiento del punto 'centro' al definir una traslación '[SRT](#srt)'. Estos puntos se denominan puntos de control, y normalmente se definen dando 4 valores en coma flotante (2 pares de coordenadas) por cada punto de control. Así que a menudo una distorsión se define en términos de varios conjuntos de 4 valores. Por ejemplo....

X1,Y1 I1,J1 X2,Y2 I2,J2 X3,Y3 I3,J3 X4,Y4 I4,J4 . . . .

Donde el punto de control Xi,Xi en la imagen de origen (relativo a su lienzo virtual) se mapea a Ii,Ji en la imagen de destino distorsionada. Sin embargo, como eloperador Distort en realidad mapea coordenadas de destino a coordenadas de origen (véase Mapeo inverso de píxeles), internamente lo anterior se usa para mapear las coordenadas I,J a las coordenadas X,Y. El resultado, no obstante, debería ser el mismo, solo que es una forma distinta de pensarlo.
Antes de la versión 6.3.6-0 de IM, cuando se introdujo por primera vez eloperador Distort, el orden de las coordenadas para los puntos de control se definía como todas las coordenadas de origen seguidas de todas las coordenadas de destino. Esto, sin embargo, hacía muy difícil determinar qué coordenadas de origen y destino se correspondían entre sí, y no permitía añadir fácilmente más puntos de control para refinar una distorsión.
--- ---
Se define de esta manera para que el movimiento de cada punto de control individual se mantenga unido en la lista de valores en coma flotante separados por comas (o espacios). También permite el uso futuro de 'archivos de puntos de control' externos. La distorsión más simple que usa puntos de control es la distorsión '[Affine](#affine)', aunque esta, como verá más adelante, suele definirse en términos de tres puntos, pero puede usar solo uno o dos movimientos de puntos de control. De hecho, '[SRT](#srt)' es simplemente un subconjunto de uno o dos puntos de una distorsión '[Affine](#affine)'. Por ejemplo, aquí movemos la 'nariz' de nuestra imagen de koala en '28,24' a la nueva posición '45,40' (como indica la flecha roja), lo que resulta en una simple 'traslación' de la ubicación de la imagen.
  magick koala.gif  -virtual-pixel white \
          -distort Affine '28,24 45,40'   koala_one_point.png

[IM Output] [IM Output]

Con dos puntos, la distorsión '[Affine](#affine)' no solo puede trasladar una imagen, sino también escalarla y rotarla (todo el rango de una distorsión '[SRT](#srt)'). Por ejemplo, aquí mapeo las 'orejas' del koala (la línea roja de '30,11' a '48,29') a una posición horizontal mayor (una línea azul de '15,15' a '60,15'), lo que requiere escalar, rotar y trasladar la imagen para que los puntos de control se muevan a esta nueva posición.

  magick koala.gif  -virtual-pixel white \
          -distort Affine '30,11 15,15  48,29 60,15'   koala_two_point.png

Por supuesto, una distorsión '[SRT](#srt)' podría haber reproducido la distorsión '[Affine](#affine)' de dos puntos anterior, salvo que aquí definimos la distorsión de una forma distinta. La forma que deba usar depende de usted, según lo que esté intentando lograr.

Coordenadas de imagen frente a coordenadas de píxel

El uso de puntos de control en el caso general es sencillo, pero se vuelve más difícil cuando necesita alinear una imagen distorsionada con otra imagen o con construcciones dibujadas. La razón es que, mientras la mayoría de los operadores en IM manejan coordenadas en términos de 'posiciones de píxel' (por ejemplo, al recortar, dibujar, etc.), las distorsiones tratan las coordenadas como 'coordenadas de imagen' matemáticas. Lo que debe recordar es que los píxeles de una imagen no son un 'punto', sino en realidad un 'área' de 1 unidad de píxel de tamaño. Es decir, un píxel ubicado en 10,10define un área cuadrada de color, que va desde 10unidades hacia abajo/a través hasta 11unidades hacia abajo y a través. En términos de coordenadas de imagen, el 'centro' del píxel está ubicado en realidad en 10.5,10.5. Es decir, hay que sumar 0,5 cuando se distorsiona una imagen para mover el centro de un 'píxel' a una ubicación específica. Así, para reposicionar los 'píxeles' de las esquinas de una imagen, necesitaría mover la imagen en términos de los píxeles ubicados en 0.5,0,5y _Width_ -0.5,_Height_ -0.5. Por otro lado, para reposicionar la imagen en términos de los 'bordes' reales de la imagen, simplemente usaría las coordenadas 0.0,0,0y _Width_ ,_Height_. Solo tiene que pensar en qué quiere posicionar realmente: el centro de los 'píxeles' de la imagen o los 'bordes' de la imagen. O si realmente importa para su problema concreto. Recuerde que si quiere dibujarotros elementos sobre su imagen distorsionada, deberá dar las posiciones de dibujo en términos de 'posiciones de píxel'. Y sí, el operador "-draw" puede dibujar líneas, círculos y otras formas usando valores en coma flotante. De forma similar, el ancho de trazo o los radios de los objetos también pueden darse como valores en coma flotante. [IM Output] [IM Output]

| _Un ancho de trazo de dibujo inferior a 1,0 no funciona bien (véaseDibujar líneas). Además, el relleno de área añade un 0,5 extra (a juego con el añadido del ancho de trazo) a los bordes del área de relleno (véase Límites del relleno de dibujo). Esto se hace independientemente del ancho de trazo realmente utilizado.

Para más información, véase Límites del relleno de dibujo. Algo que considero un error._

Puntos de control mediante escapes de porcentaje

También puede usar escapes de porcentaje dentro de los argumentos de distorsión. Por ejemplo, puede extraer los atributos de una imagen y luego usarlos para redimensionar otra imagen de modo que coincida con la primera. Aquí obtengo el tamaño de la imagen incorporada "rose:" y luego uso una distorsión '[Affine](#affine)' para redimensionar la imagen más grande "logo:" al mismo tamaño (sin preservar la relación de aspecto). |

   magick rose: -set option:rw %w -set option:rh %h +delete \
           logo: -alpha set -virtual-pixel transparent \
           +distort Affine '0,0 0,0     %w,0 %[rw],0   0,%h  0,%[rh]' \
           +repage logo_sized_as_rose.png

[IM Output]
Tenga en cuenta que la distorsión generará una 'imagen en capas' ligeramente más grande sobre un lienzo virtual (incluyendo un desplazamiento negativo), razón por la cual necesité incluir un "[+repage](https://imagemagick.org/command-line-options/#repage)" en el ejemplo anterior. También tendrá bordes difusos, ya que la distorsión genera una distorsión exacta o verdadera de la imagen, y no una imagen redimensionada ortogonal y depurada. Para ejemplos más avanzados sobre el uso del operador Distort para redimensionar imágenes, exactamente como lo hace el operador Resize, véase Distort frente a Resize, así como el método Distort Resize más abajo. También puede usar escapes de porcentaje para calcular distorsiones basadas en la posición de una imagen dentro de la lista de imágenes actual. Hay ejemplos de esto en Distorsiones animadas.

Ajuste por mínimos cuadrados de puntos de control

Si proporciona más de 3 puntos de control para una distorsión '[Affine](#affine)', o más de 4 puntos para las distorsiones '[Perspective](#perspective)' o '[Bilinear](#bilinear)', ImageMagick realizará una media por mínimos cuadrados sobre todos los puntos dados para hallar una representación 'media' de esas distorsiones. Esto significa que si intenta hacer coincidir una imagen con otra (una técnica conocida como 'registro de imágenes'), puede definir más del número mínimo de puntos necesarios para que el resultado sea una distorsión más precisa. Por supuesto, si uno o más de esos puntos no 'encajan' bien con los demás, el resultado se verá sesgado por el punto 'anómalo', ya que IM intenta hallar el mejor ajuste usando todos los puntos de control dados, incluido el incorrecto. En algunas situaciones puede ser necesario algún control para hallar y eliminar los 'pares de coordenadas incorrectos'.

Puntos de control desde archivos

La lista de números (argumentos) de una distorsión también puede leerse desde un archivo usando la sintaxis '@filename', igual que puede introducir texto para cosas como "[-annotate](https://imagemagick.org/command-line-options/#annotate)" y "[label:](text.html#label)" (véase Caracteres de escape en argumentos de texto). Por ejemplo, puede especificar una distorsión así...

  magick input.png  -distort Perspective '@file_of_coords.txt' output.png

El nombre de archivo puede ser simplemente '@-' para indicar que se lea el archivo desde la entrada estándar. El archivo en sí se leerá como una cadena y se tratará como la lista de coordenadas (argumentos) que necesita la distorsión correspondiente. Como los números pueden estar separados por comas o por espacios en blanco, eso significa que los pares de coordenadas pueden ordenarse limpiamente como un par de coordenadas por línea de la forma...

   X1   Y1   I1   J1
   X2   Y2   I2   J2
   X3   Y3   I3   J3
   X4   Y4   I4   J4
   ....

Esto, junto con el ajuste por mínimos cuadrados, hace que el uso del registro de imágenes sea muy práctico. Como el archivo es simplemente una lista de cuatro números por línea, puede usar otras herramientas de procesamiento de texto y de scripting como "cut", "paste", "column", y herramientas más avanzadas como "sed", "awk", "perl", etc., para manipular las coordenadas. El uso de archivos de coordenadas y de argumentos de distorsión cobrará mayor importancia con distorsiones más avanzadas, como la distorsión '[Shepards](#shepards)', y las futuras distorsiones planeadas 'Grid' y "Mesh', donde pueden intervenir cientos de pares de coordenadas.


Métodos de distorsión afín (de tres puntos)

Distorsión afín

Tanto la distorsión '[SRT](#srt)' como las formas de uno y dos puntos de la distorsión 'Affine' mostradas arriba son en realidad simplificaciones de la forma completa de 3 puntos de la distorsión 'Affine'. De hecho, si estudia la salida de "-verbose" de cualquier distorsión '[SRT](#srt)' (véase ajuste de distorsión detallada para un ejemplo), descubrirá que internamente es en realidad una distorsión '[AffineProjection](#affine_projection)' (véase más abajo). El único efecto de distorsión que los métodos anteriores no podían manejar por completo eran los 'cizallamientos', similares a los que proporcionaría el operador Shear. Para eso necesita usar una distorsión afín de tres puntos. Puede pensar en esto como una distorsión de tres puntos, imaginando el primer mapeo de coordenadas como un 'origen' y los otros dos mapeos de coordenadas como vectores desde ese origen. Por ejemplo, aquí dibujo un texto y superpongo un 'vector' rojo y otro azul para definir los tres puntos de control relativos a ese texto. Ahora, moviendo las coordenadas (como coordenadas de imagen) de esas dos líneas, podemos trasladar, rotar, escalar y cizallar esa imagen de texto, para que se ajuste a la nueva ubicación de esas líneas.

  magick -background lightblue -fill Gray -font Candice \
      -size 100x100 -gravity center label:Affine\! \
      -draw 'fill blue stroke blue path "M 3,60 32,60 M 27,58 27,62 32,60 Z"' \
      -draw 'fill red  stroke red  path "M 3,60  3,30 M  1,35  5,35  3,30 Z"' \
      label_axis.png
  magick label_axis.png \
          -distort Affine ' 3.5,60.5   3.5,60.5
                           32.5,60.5  32.5,60.5
                            3.5,30.5  33.5,20.5' label_axis_distort_shear.png
  magick label_axis.png \
          -distort Affine ' 3.5,60.5   3.5,60.5
                           32.5,60.5  27.5,85.5
                            3.5,30.5  27.5,35.5' label_axis_distort_rotate.png
  magick label_axis.png \
          -distort Affine ' 3.5,60.5  30.5,50.5
                           32.5,60.5  60.5,80.5
                            3.5,30.5  30.5,5.5' label_axis_distort_affine.png

[IM Output] [IM Output] [IM Output] [IM Output]

En el primer ejemplo solo se modificó la tercera coordenada (la de la línea roja vertical), lo que provocó que la imagen se cizallara y se estirara a lo largo del eje Y. Por supuesto, no tiene por qué limitarse solo al eje Y. Los ejemplos posteriores hacen cambios más radicales en la imagen, incluyendo rotaciones y traslaciones. Por supuesto, el operador Annotate Text también puede sesgar texto real de esta misma manera, aunque solo con cambios en el ángulo. Ese operador no escalará ni agrandará el texto en una dirección concreta. Es decir, puede rotar un 'vector' pero no puede estirarlo más largo o más corto. Véase Uso de los argumentos de Annotate para una tabla de ejemplos. La distorsión afín puede realizar este tipo de distorsión para cualquier imagen, y no solo para texto dibujado. Afín usando menos o más de tres pares de coordenadas Si solo se proporcionan 1 o 2 pares de puntos de control, IM usará una forma más limitada de distorsión afín para igualar el movimiento de esos menos puntos. Por ejemplo, con solo 1 par de coordenadas, se limita a traslaciones de la imagen sin escalado. Con 2 puntos se limita a distorsiones de tipo '[Scale-Rotate-Translation](#srt)' (sin cizallamientos). Véase la discusión anterior sobre Distorsiones mediante puntos de control para ejemplos. Si se dan más de 3 puntos de control a una distorsión '[Affine](#affine)', IM usará el ajuste por mínimos cuadrados para hallar la mejor distorsión afín de '3 puntos' que coincida con todos los pares de coordenadas dados. Eso significa que los puntos de control de la imagen de origen pueden no mapearse exactamente a los puntos de control de la imagen de destino, sino a un 'promedio' de mejor ajuste de todos los puntos dados. Por ejemplo, si tiene un escaneo de un documento, podría localizar y mapear las 4 esquinas del documento para una distorsión afín que corrija la rotación y el escalado del documento. De esta manera puede obtener un mejor ajuste 'promedio' basado en 4 puntos en lugar de 3. Tenga en cuenta que, aunque más coordenadas pueden producir una distorsión mejor y más precisa, si un par de coordenadas es muy malo, el ajuste por mínimos cuadrados podría no producir un buen ajuste en absoluto. Puede ser necesario algún control para eliminar los 'pares de coordenadas incorrectos'. Future: Add some code to IM to report how 'accurate' each input coordinate pair is relative to the others to help determine what 'bad points' should be eliminated by the user.

Distorsión por proyección afín

Como ya he mencionado, los diversos argumentos de una distorsión '[SRT](#srt)' y los puntos de control de una distorsión '[Affine](#affine)' se transforman matemáticamente en 6 números especiales que representan los 'coeficientes' de una 'Proyección afín'. Estos números de una proyección afín son los coeficientes usados para el mapeo directo de los puntos de la imagen de origen a la imagen de destino. Es decir, son los valores matemáticos usados para mapear un x,y de la imagen de origen a un i,j de la imagen de destino. Los 6 argumentos en coma flotante son (en el orden en que deben darse)...

sx, rx, ry, sy, tx, ty

Estos a su vez forman las expresiones de distorsión.. Xd = | sx*Xs + ry*Ys + tx | , | Yd = | rx*Xs + sy*Ys + ty |
---|---|---|---|---|---
Donde "Xs,Ys" son las coordenadas de la imagen de origen y "Xd,Yd" son las coordenadas de la imagen de destino. Internamente, Distort de ImageMagick invertirá las ecuaciones anteriores para realizar el mapeo de píxeles apropiado y mapear las coordenadas "Xd,Yd" para buscar el color en "Xs,Ys" en la imagen de origen. Para más información sobre cómo afectan los distintos valores de la matriz de proyección afín a la imagen, véase la subpágina Transformaciones de matriz afín. Si ya tiene estos coeficientes precalculados (digamos, extraídos de la salida detallada de la distorsión, o calculados por usted mismo mediante otros métodos a partir de otras formas de argumentos de entrada), entonces puede suministrarlos directamente a IM para distorsionar la imagen. Por ejemplo, aquí 'cizallo' la imagen pero usando un ángulo para calcular los coeficientes, en lugar del movimiento de puntos de control. |

   angle=-20
   tan=`magick xc: -format "%[fx:tan( $angle *pi/180)]" info:`
   magick koala.gif -alpha set -virtual-pixel Transparent \
           +distort AffineProjection "1,$tan,0,1,0,0" +repage \
           koala_affine_proj.png

[IM Output]
La forma más antigua de hacer esta distorsión en ImageMagick era usar el par de operaciones "-affine" y "-transform". Sin embargo, a partir de IM v6.4.2-8 esto es simplemente una llamada sencilla a 'AffineProjection' usando la forma 'plus' o de 'mejor ajuste' del operador Distort. Véase la subpágina Transformaciones de matriz afín para más detalles.

Ejemplos de distorsión afín

Mosaico afín

Los tres métodos de distorsión de tipo afín que hemos visto hasta ahora también ofrecen formas interesantes de generar diversos patrones de mosaico, basados en una imagen distorsionada.

  magick checks.png    -alpha set    -virtual-pixel tile \
          -distort  ScaleRotateTranslate  '20,20  .5  30' \
          checks_srt_tile.png
  magick checks.png    -alpha set    -virtual-pixel tile \
          -distort  Affine  '0,0 10,10   0,89 10,50   89,0 50,0' \
          checks_affine_tile.png
  magick checks.png    -alpha set    -virtual-pixel tile \
          -distort  AffineProjection  '0.9,0.3,-0.2,0.7,20,15' \
          checks_amatrix_tile.png

[IM Output] [IM Output] [IM Output] [IM Output]

Usar un mapeo de distorsión de esta manera es en realidad cómo funciona el 'mapeo de texturas' en las bibliotecas y juegos de gráficos 3D. La única diferencia es que ellos mapean coordenadas tridimensionales de superficies de vuelta a una imagen bidimensional. Incluso la distorsión 'sin efecto' ("-distort SRT 0"), con un viewport de distorsión apropiado, proporciona una forma útil de crear mosaicos de secuencias enteras de imágenes, como los mosaicos de brillo animados.

  magick glitter_blue.gif -virtual-pixel tile \
          -filter point -set option:distort:viewport 100x100 -distort SRT 0 \
          glitter_blue_tiled.gif

[IM Output] [IM Output]

Tenga en cuenta que también usé un "[-filter](https://imagemagick.org/command-line-options/#filter) point" para desactivar el remuestreo EWA, de modo que se acelere la operación y, además, se asegure una copia perfecta (sin remuestrear) de los píxeles de la imagen de origen. El viewport de distorsión también puede especificar un desplazamiento, para 'desplazar' las imágenes en mosaico sobre la imagen resultante.

Cubos en 3D, mediante superposición afín

La distorsión '[Affine](#affine)', con sus puntos de control, es ideal para generar cubos ortográficos e isométricos (véase Wikipedia, Proyección ortográfica y Proyección isométrica para las definiciones), a partir de tres imágenes. Todo lo que necesita hacer es calcular cuatro puntos de control en una imagen de destino. Como usaremos una técnica de superposición de imágenes, los puntos pueden incluso tener valores negativos, lo que permite a IM ajustar el tamaño final de la imagen según las imágenes deformadas generadas. Para este ejemplo elegiré los puntos de control '0,0' para el centro del cubo, y tres puntos equidistantes alrededor de ese punto central, en '-87,-50', '87,-50' y '0,100'. Todo lo que entonces necesito hacer es mapear las esquinas apropiadas de tres imágenes (preferiblemente cuadradas) a estos puntos de control. |

  magick \
     \( lena_orig.png -alpha set -virtual-pixel transparent \
        +distort Affine '0,512 0,0   0,0 -87,-50  512,512 87,-50' \) \
     \( mandrill_orig.png -alpha set -virtual-pixel transparent \
        +distort Affine '512,0 0,0   0,0 -87,-50  512,512 0,100' \) \
     \( pagoda_sm.jpg -alpha set -virtual-pixel transparent \
        +distort Affine '  0,0 0,0   0,320 0,100    320,0 87,-50' \) \
     \
     -background none -compose plus -layers merge +repage \
     -bordercolor black -compose over -border 5x2     isometric_cube.png

[IM Output]
Tenga en cuenta que usé las coordenadas de los bordes reales de la imagen al distorsionarla. Esto significa que, en términos matemáticos, las imágenes deberían encajar exactamente entre sí. Note también que no simplemente 'compuse' (usando la composición alfa Over predeterminada) las imágenes juntas. Si lo hiciera, obtendría 'huecos' ligeramente transparentes entre las imágenes. La forma correcta (como se muestra) es usar la composición alfa Plus para unir piezas 'conectadas por los bordes', lo que dará como resultado una unión perfecta sin huecos transparentes. Para más información, véase Alinear dos imágenes enmascaradas. Después añadí un borde extra y eliminé toda la transparencia. No es obligatorio, y podría usar fácilmente cualquier fondo (o "none"), pero hacerlo resaltará cualquier 'hueco' que pueda haber en sus imágenes.
[IM Output] A la derecha se muestra una ampliación de una de esas uniones en la imagen, que evidencia la ausencia de cualquier hueco 'relleno de negro' a lo largo de la unión. Un método alternativo para crear un cubo isométrico, sin usar "-distort", se da en Cubo isométrico mediante cizallamientos. No obstante, esta técnica no le permite usar coordenadas subpíxel (no es que usara ninguna en el ejemplo anterior, pero podría haberlo hecho), sino que está restringida a posicionar imágenes usando coordenadas de píxel entero (enteros).

Sombras en 3D, mediante cizallamientos afines

Los mismos métodos de superposición usados arriba también pueden emplearse para generar atractivas sombras tridimensionales de formas extrañas. Esto añade una sombra a cualquier forma 'plana' que esté de pie. Por ejemplo, creemos una forma con una base plana, para que pueda mantenerse en pie. |

  magick -background None -virtual-pixel Transparent -fill DodgerBlue \
          -pointsize 72 -font Ravie  label:A   -trim +repage \
          -gravity South -chop 0x5  standing_shape.png

[IM Output]
Tenga en cuenta que la 'forma' tiene una base plana que es también la última fila de la imagen. Esto es importante porque distorsionaremos la forma a lo largo de esa fila, de modo que la sombra se conecte a la forma de pie a lo largo de esa fila. Aquí está el comando para generar la sombra 3-D de esta 'forma de pie' |

  magick standing_shape.png   -flip +distort SRT '0,0 1,-1 0' \
          \( +clone -background Black -shadow 60x5+0+0 \
             -virtual-pixel Transparent \
             +distort Affine '0,0 0,0  100,0 100,0  0,100 100,50' \
          \) +swap -background white -layers merge \
          -fuzz 2% -trim +repage   standing_shadow.jpg

[IM Output]
Lo anterior realiza unos cuantos pasos para lograr el resultado mostrado. El más complicado, sin embargo, es esa primera línea. Esto voltea la imagen y luego hace un 'volteo por distorsión' para devolverla de nuevo. El resultado de esto es que la fila inferior queda ahora ubicada de modo que tiene un valor de Y=0 en el lienzo virtual. Es decir, a toda la imagen se le dio un desplazamiento negativo para posicionarla de modo que la fila inferior pasara por el origen del lienzo virtual. Al hacer este 'truco', podemos usar un 'cizallamiento afín' muy simple sobre la 'sombra' extraída para distorsionarla. Así, no necesitamos conocer el tamaño de la imagen de la forma para distorsionar la sombra, pero aun así logramos mantener todo 'alineado', ya que todo permanece sincronizado a lo largo de la fila inferior (Y=0) de la imagen original. Puede ajustar la dirección en que cae la sombra y su longitud simplemente ajustando la coordenada final ('100,50') del 'cizallamiento afín'. Los dos primeros 'pares de coordenadas' no deben modificarse, ya que estos 'fijan' la sombra a la imagen original a lo largo de la fila inferior. No obstante, tenga en cuenta que hasta el último paso, todas las imágenes contendrán desplazamientos negativos del lienzo virtual, por lo que se aconseja precaución si planea ver o guardar las imágenes de procesamiento intermedias. El único problema de este efecto de sombra es que es un 'difuminado uniforme'. Es decir, la sombra no es realista. En realidad, la sombra debería ser nítida donde se une a la 'forma de pie' y volverse más difusa a medida que la sombra se aleja. Esto, sin embargo, puede hacerse usando un mapeo de difuminado variable, como el usado en Fuente con sombra de difuminado por distancia.

Sombra en 3D, mediante compresión de perspectiva

Esta es otra forma de añadir difuminado variable a la sombra; aunque en realidad no la recomiendo, es bastante sencilla de implementar. Este ejemplo se desarrolló antes de que se añadiera el mapeo de difuminado variable a ImageMagick. Básicamente, primero distorsiona la forma de sombra inicial usando una distorsión de perspectiva (que se examina en detalle más abajo), para comprimir fuertemente la 'parte lejana' de la sombra, difuminándola, y luego expande esa compresión distorsionándola hasta su posición final de 'cizallamiento afín' que usamos antes. |

  magick standing_shape.png   -flip +distort SRT '0,0 1,-1 0' \
          \( +clone   -virtual-pixel Transparent -mattecolor None \
             +distort Perspective \
                '0,0 0,0  100,0 100,0   0,-100 45,-100   100,-100 60,-100' \
             -fuzz 2% -trim   -background Black -shadow 60x3+0+0 \
             +distort Perspective \
                '0,0 0,0  100,0 100,0   45,-100 -100,-50   60,-100 0,-50' \
          \) +swap -background white -layers merge \
          -fuzz 2% -trim +repage     standing_shadow_var.jpg

[IM Output]
Esto es casi exactamente igual que el ejemplo original de sombreado 3D, pero con algunos pasos extra. La forma original se distorsiona primero en un trapecio, y luego se recorta cualquier espacio sobrante para acelerar el siguiente paso. Después extraemos una sombra difuminada de la forma distorsionada. Una vez creada la imagen de la sombra a partir de la imagen distorsionada, se usan los mismos puntos de control para deshacer la distorsión de la imagen de la sombra y moverla a su posición como un cizallamiento afín. La clave es que el difuminado de la sombra ocurre sobre una imagen distorsionada, que luego se des-distorsiona (y en este caso, al mismo tiempo, se le aplica un cizallamiento afín). Como resultado, el difuminado también se distorsiona y se expande, de modo que se difumina más en la parte superior de la sombra y mucho menos a lo largo de la línea base. Como resultado del difuminado de perspectiva, obtenemos un difuminado variable que debería alcanzar su punto máximo a unos 100 píxeles de la línea base del suelo. Según lo definido por los puntos de control del difuminado de perspectiva inicial.

Redimensionar imágenes mediante Distort

Tanto Distort como Resize son en realidad muy similares en muchos aspectos. Ambos son operadores de distorsión de imágenes, y ambos usan el mapeo inverso de píxeles para crear la imagen resultante. Ambos también hacen uso del ajuste "[-filter](https://imagemagick.org/command-line-options/#resize)" y de sus controles expertos, para la determinación del color, aunque lo hacen de una forma muy distinta. Resize es una operación de distorsión de imágenes simplificada (y mucho más común), que le permite hacer muchas optimizaciones. Está alineada ortogonalmente, lo que le permite usar un método de filtrado ortogonal de imágenes en 2 pasadas al redimensionar. Es decir, primero dimensiona en una dirección y luego en la otra, usando una imagen temporal intermedia. Además, como el factor de escala es constante en toda la imagen de destino, con los bordes alineados a una dimensión de píxel entero, el algoritmo puede simplificar enormemente su procesamiento y los requisitos de caché del filtro que usa. Todas estas limitaciones permiten diversas optimizaciones que la hacen muy rápida en comparación con el trabajo que debe hacer la distorsión. Distort también puede redimensionar imágenes, pero lo hace en una sola pasada, que convierte directamente la imagen original en la nueva imagen resultante. No necesita alinear los bordes a posiciones de píxel entero, y podría rotar y escalar cada posición de píxel. En otras palabras, es un operador mucho más general que le exige hacer mucho procesamiento extra por cada píxel del resultado final, con menos lugares para la optimización. Para que Distort genere una imagen equivalente a Resize, necesita seguir exactamente las mismas limitaciones y usar algunos trucos complejos de procesamiento de imágenes. Esto se discutió en los foros de IM, en Redimensionado correcto (usando distorsiones), y dio como resultado una técnica de redimensionado por distorsión equivalente basada en el uso del método de distorsión afín. El método de distorsión 'Resize' resultante se añadió a la versión 6.6.9-2 de ImageMagick. La versión de interfaz de línea de comandos (CLI) de esta distorsión aceptará y procesará exactamente el mismo argumento de geometría que Resize, incluyendo la ligera discrepancia en los factores de escala para las dos dimensiones, lo que la convierte en una alternativa directa de redimensionado. |

  magick logo:  -distort Resize 150x  logo_resized.png

[IM Output]
| _Otras interfaces de API del método de distorsión 'Resize' solo aceptarán dos números como argumentos, que se tratan como el tamaño entero final de la imagen resultante. Por el momento no aceptarán un argumento de geometría real con sus diversos indicadores de control de redimensionado, que modifican el tamaño final de la imagen. Es decir, indicadores como el porcentaje, redimensionar solo más grande/más pequeño, o incluso la preservación de la relación de aspecto, no están disponibles.

Queda en manos de los mantenedores de esas API añadir tal soporte para este método especial de distorsión de imágenes._
---|---
La diferencia real entre el Distort Resize anterior y el operador Resize normal es que la versión de distorsión usa un filtro cilíndrico (elíptico) de una sola pasada, mucho más lento, para determinar el color final de todos y cada uno de los píxeles. En otras palabras, proporciona una comparación directa entre filtros ortogonales de 2 pasadas (resize) y filtros cilíndricos bidimensionales de una sola pasada (distort resize). Véase Distort frente a Resize para una de esas comparaciones.

Internos de Distort Resize

A continuación se muestran las operaciones equivalentes que el Distort Resize anterior realizó internamente.

  magick logo:  -alpha set -virtual-pixel transparent \
          +distort Affine '0,0 0,0   %w,0 150,0   0,%h 0,113' \
          -alpha off  -crop 150x113+0+0 +repage   distort_resize.png

Los valores '150' y '113' (usados en dos lugares) son el tamaño deseado de la imagen final redondeado al entero más cercano. Se calcularon para intentar preservar lo mejor posible la relación de aspecto de la imagen, ateniéndose a la limitación del tamaño entero final. Normalmente los calcula ImageMagick a partir del argumento de geometría de redimensionado dado, usando una función de API separada. Luego habilita la transparencia y los píxeles virtuales transparentes, de modo que los 'píxeles virtuales' externos no participen en el cálculo del color final del píxel. Cuando la distorsión se completa, la transparencia se elimina de nuevo (se desactiva), y los píxeles de 'búfer' añadidos por la distorsión se eliminan mediante un recorte de imagen. Debido al uso de píxeles transparentes, el comando anterior solo funcionará correctamente para imágenes que no contengan ninguna transparencia, como la imagen incorporada "logo:" del ejemplo anterior. Esta es la versión mucho más compleja, que se requiere para separar los efectos de los píxeles virtuales de cualquier transparencia posiblemente existente en la imagen.

  magick logo: -alpha set -virtual-pixel transparent \
          \( +clone -alpha extract -alpha opaque \) \
          +distort Affine '0,0 0,0   %w,0 150,0   0,%h 0,113' \
          -alpha off -crop 150x113+0+0 +repage \
          -compose CopyOpacity -composite      distort_resize_trans.png

Esto realiza dos distorsiones: primero para distorsionar la imagen y luego para distorsionar el canal alfa (transparencia) por separado, usando en cada caso transparente para eliminar los efectos del píxel virtual. Como resultado, es al menos dos veces más lento que el caso en que no hay transparencia presente en la imagen original. Ambas técnicas están implementadas internamente por el método Distort Resize. Como tal, este 'método' es realmente una 'macro' de conveniencia para los usuarios, y no un método de distorsión real, que es una distorsión 'afín'.


Métodos de distorsión de cuatro puntos

Distorsión de perspectiva

Probablemente el tipo de distorsión más solicitado haya sido una operación rápida de distorsión de perspectiva. Es una distorsión de 4 puntos, por lo que requiere al menos 4 pares de puntos de control, es decir, 16 valores de punto flotante. Por ejemplo, aquí tengo la imagen de un edificio. A partir de esta imagen localicé manualmente la posición de 4 puntos (en rojo). También definí la posición final a la que se transforman esos puntos en la imagen final (en azul), para 'enderezar' o 'rectificar' la fachada del edificio.

  magick building.jpg \
          -draw 'fill none stroke red polygon 7,40 4,124, 85,122, 85,2' \
          building_before.jpg
  magick building.jpg \
          -draw 'fill none stroke blue polygon 4,30 4,123, 100,123, 100,30' \
          building_after.jpg

[IM Output] [IM Output] [IM Output]

Para realizar la distorsión de imagen propiamente dicha, solo hay que pasar esas coordenadas al método 'perspective' de "-distort".

  magick building.jpg -alpha set -virtual-pixel transparent \
         -distort Perspective \
              '7,40 4,30   4,124 4,123   85,122 100,123   85,2 100,30' \
          building_pers.png

[IM Output] [IM Output]

Observe el área en blanco en la parte superior derecha, donde la distorsión 'perdió' los datos de píxeles de la imagen de origen. Lo que IM hace en esta situación se controla con la opción "-virtual-pixel" (consulte Virtual Pixel). Lo que se nota menos es que una pequeña parte del borde más a la izquierda de la imagen original también se 'pierde' por el mismo motivo. A modo de curiosidad, invirtamos también la distorsión, intercambiando las coordenadas de cada par de mapeo. Esto nos permite ver cuánto se degrada la imagen con la distorsión.

  magick building_pers.png  -alpha set -virtual-pixel transparent \
         -distort Perspective \
              '4,30 7,40   4,123 4,124   100,123 85,122   100,30 85,2' \
          building_pers_rev.png

[IM Output] [IM Output] [IM Output]

No está mal. Hay bastante 'borrosidad', pero no se puede evitar. Observe que la 'borrosidad' es peor en el lado derecho de la imagen, que es donde más se comprimió. Todas las distorsiones sufren este problema de compresión, por lo que siempre conviene distorsionar a partir de una imagen original, en lugar de distorsionar una imagen ya distorsionada. Aquí hay otro ejemplo de uso de esta transformación, empleando la imagen de prueba especial en damero que creamos antes, que distorsionamos y luego invertimos.

  magick checks.png        -alpha set    -virtual-pixel transparent \
          -distort Perspective '0,0,0,0  0,90,0,90  90,0,90,25  90,90,90,65' \
          checks_pers.png
  magick checks_pers.png   -alpha set    -virtual-pixel transparent \
          -distort Perspective '0,0,0,0  0,90,0,90  90,25,90,0  90,65,90,90' \
          checks_pers_rev.png

[IM Output] [IM Output] [IM Output]

Puede verse la ligera borrosidad provocada por la compresión de imagen, pero la imagen queda básicamente restaurada. Lo que ocurre en realidad es que IM usa todos los pares de puntos de control proporcionados para calcular los coeficientes apropiados de una '[Perspective Projection](#perspectiveprojection)' (véase a continuación). Si incluye la opción Verbose, podrá ver tanto los coeficientes como el equivalente FX casero que IM utiliza internamente para realizar esta distorsión. Si se proporcionan 3 o menos pares de puntos de control, IM recurrirá automáticamente a la distorsión más simple '[Affine](#affine)'. Mientras que con más de 4 puntos (para 'registro de imagen') se aplicará un ajuste por mínimos cuadrados para hallar la distorsión que mejor se adapte a todos los puntos de control dados. FUTURO: Alternativa. Las cuatro coordenadas también podrían representar un triángulo y un punto central. Podría fijar el triángulo y mover el punto central, o fijar ese centro y mover las otras tres coordenadas, para generar la vista en perspectiva. Si desea ver con más detalle cómo funciona la distorsión, consulte Perspective Internals más abajo. También puede consultar una implementación en Postscript que se presentó en un artículo en PDF, Perspective Rectification, de Gernot Hoffmann. Eche también un vistazo a Leptonica Affine and Perspective Transforms.

Visualización de horizontes lejanos

Puede producir efectos muy inusuales con las distorsiones de perspectiva si ajusta las coordenadas para generar un 'punto de fuga' dentro de los límites de la imagen. |

  magick checks.png -mattecolor DodgerBlue \
          -virtual-pixel background -background Green \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          checks_horizon.png

[IM Output]
Pues bien, usamos 'Green' para los píxeles virtuales que 'rodean' la imagen original, lo cual habilitamos mediante la opción de fondo de Virtual Pixel. Pero lo más interesante es la aparición del color 'azul' que se definió con la opción "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)". Este color 'azul' representa un área donde los píxeles generados por la distorsión son no válidos , y en tales áreas el operador "-distort" simplemente emitirá el valor de "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)". En una distorsión de perspectiva, cualquier píxel que acabe en el 'cielo' de la imagen resultante se clasificará como no válido. Además, se define el 'cielo' como el lado del 'horizonte' en el que la imagen de origen no aparecerá. El 'cielo' solo aparecerá en las imágenes distorsionadas en perspectiva cuando la imagen resultante quede muy escorzada por la distorsión. Si no desea un 'cielo' en el resultado final, lo mejor es definir tanto "[-background](https://imagemagick.org/command-line-options/#background)" como "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" con el mismo color. La distorsión de perspectiva se vuelve más interesante cuando se utiliza alguna de las opciones especiales de Virtual Pixel de teselado infinito. Por ejemplo, aquí usamos la opción '[tile](misc.html#tile)' para generar un plano teselado infinitamente. |

  magick checks.png  -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_tile.png

[IM Output]
Una advertencia sobre esta imagen. Solicitar una imagen teselada infinitamente es muy lento de generar. Cuanto mayor sea la imagen, más lento será. Puede supervisar el progreso de "[-distort](https://imagemagick.org/command-line-options/#distort)" (o de cualquier otra tarea lenta de procesamiento de imagen) usando la opción de control operacional "[-monitor](https://imagemagick.org/command-line-options/#monitor)". Básicamente, para un único píxel cercano al horizonte, ImageMagick necesita promediar una enorme cantidad de píxeles de la imagen original para determinar el color apropiado. Esto puede llevar mucho tiempo. ImageMagick intenta limitar el tiempo que dedica a manejar estos píxeles cercanos al horizonte, almacenando información en caché y aprovechando cierto conocimiento integrado de las distintas opciones de Virtual Pixel, pero aun así puede tardar bastante. Para más detalles sobre este método, consulte Area Resampling más arriba. Otra imagen en perspectiva teselada infinitamente puede generarse usando una opción aleatoria de Virtual Pixel... |

  magick checks.png  -virtual-pixel random -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_random.png

[IM Output]
Lo que sucede es que todos los píxeles virtuales que rodean la imagen son simplemente selecciones aleatorias de cualquier píxel dentro de la propia imagen. El resultado es un suelo formado por ruido aleatorio que se va suavizando y difuminando a medida que se mira hacia el horizonte de la imagen. Da una sensación natural de profundidad, sin ningún patrón repetitivo concreto. Aquí repetí lo anterior pero con una imagen de origen en blanco y negro puro. Sin embargo, no me interesa la imagen distorsionada en sí, sino solo el patrón 'random' de Virtual Pixel que se generó, así que cambié qué parte del 'espacio de imagen distorsionado' estoy observando, usando la opción especial '-set option:distort:viewport'. Esta opción anula el tamaño y la posición normales del área del espacio distorsionado que se visualiza. En este caso, un área que contiene únicamente píxeles virtuales, y no la imagen distorsionada. |

  magick -size 90x90 pattern:gray50 -alpha set \
       -virtual-pixel random -mattecolor none \
       -set option:distort:viewport 120x120+100-15 \
       -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
       +repage -size 120x50 gradient:dodgerblue-tomato \
       -compose DstOver -composite    sunset_horizon.png

[IM Output]
Para completar la imagen, eliminé el desplazamiento del viewport (usando "[+repage](https://imagemagick.org/command-line-options/#repage)") y, mediante composición por debajo o DstOver, coloqué un degradado de colores de atardecer en el 'cielo' transparente (definido con "[alpha setmattecolor](https://imagemagick.org/command-line-options/#mattecolor)"). Una imagen muy interesante que podría usarse como telón de fondo para otros trabajos de procesamiento de imagen. Puede ajustar los parámetros de la distorsión para regular la altura y la inclinación del horizonte. Aquí hay una prueba más tradicional de una distorsión de perspectiva teselada. |

  magick pattern:checkerboard -scale 120x120 -normalize \
          -virtual-pixel tile  -distort Perspective \
             '0,0 10,61   119,0 60,60   0,119 5,114   119,119 125,110' \
          checkered_plain.gif

[IM Output]
En mis estudios encontré que la prueba anterior es engañosa, ya que no da una indicación real de la calidad de la técnica de remuestreo de área para escalas cercanas a la unidad de una imagen (área en primer plano, en vez de áreas lejanas). Es decir, un examen detallado de los problemas de remuestreo como los descritos en Resampling Artefacts. Esta última imagen también muestra un punto de 'corte' cerca del horizonte donde ImageMagick decidió que no valía la pena intentar determinar el color apropiado para un píxel (considerando la opción actual de virtual pixel), sino que cortocircuita el algoritmo EWA y usa el color promedio de toda la imagen. Solo es visible en esta imagen debido al patrón diagonal de color a gran escala que está presente en ella. El color promedio de una imagen se calcula una sola vez por operación de distorsión, y únicamente cuando se necesita por primera vez. Al usarlo, ImageMagick ahorra una enorme cantidad de tiempo calculando colores cercanos al horizonte, cuando lo habitual es que el resultado sea el color promedio de la imagen. Esto sucede cuando la elipse se alarga tanto que supera los límites del punto flotante, o cuando el número de píxeles de muestreo (paralelogramo que delimita la elipse) llega a ser 4 veces mayor que la imagen de origen. Actualmente esto no es configurable por el usuario.

Cajas 3D, capas en perspectiva

La forma 'plus' de "+distort", que garantiza que toda la imagen distorsionada se conserve en una capa (o 'lienzo virtual') correctamente posicionada, está diseñada de modo que, si se usan los mismos 'puntos de control' para distorsionar las imágenes, esos puntos quedarán alineados en el 'espacio virtual'. Esto significa que, si las imágenes se fusionan por capas entre sí, también quedarán alineadas según los puntos de control. Por ejemplo, aquí generamos dos imágenes, una 'portada' y un 'lomo', de modo que dos puntos de control de borde queden alineados entre sí, para formar el lomo de una caja.

  # Generate a Spine Image
  magick -size 200x40 xc:skyblue \
    -pointsize 20 -gravity north -annotate +5+0 'IM Examples' \
    -pointsize 10 -gravity south -annotate +0+0 'ImageMagick' \
    -stroke blue -strokewidth 2 -draw 'line 30,0 30,40' \
    -rotate -90 box_spine.jpg

  # generate the front cover
  magick -size 150x200 xc:skyblue \
    -fill black -pointsize 20 -gravity north -annotate +0+5 'IM Examples' \
    -fill blue -pointsize 15 -gravity northeast -annotate +5+28 'Box Set' \
    -fill black -pointsize 15 -gravity south -annotate +0+5 'ImageMagick' \
    -stroke blue -strokewidth 2 -draw 'line 0,169 150,169' \
    \( logo.gif -resize 100x100 \) \
    -gravity center -compose multiply -composite box_front.jpg

  # Distort both images and merge using common points.
  magick \
    \( box_spine.jpg -alpha set -virtual-pixel transparent \
       +distort Perspective \
           '0,0 -30,20  0,200 -30,179  40,200 0,200  40,0 0,0' \) \
    \( box_front.jpg -alpha set -virtual-pixel transparent \
       +distort Perspective \
           '0,0 0,0  0,200  0,200  150,200 100,156  150,0 100,30' \) \
    \
    -background black -compose plus -layers merge  +repage \
    -bordercolor black -compose over -border 15x2    box_set.jpg

[IM Output] [IM Output] [IM Output]

Observe también el uso de la composición alfa Plus para unir piezas 'conectadas por el borde'. Esto es necesario para evitar la generación de un 'hueco semitransparente' entre las dos imágenes. Para más información, consulte el ejemplo de 3D Cube anterior, así como Aligning Two Masked Images. Usar posiciones como estas hace que casi toda la imagen del 'lomo' quede distorsionada en una posición 'x' negativa. Por tanto, la imagen resultante tiene un desplazamiento negativo en el lienzo virtual. IM no tiene problemas para hacer esto cuando se usa la versión por capas "+distort" del operador. El operador Layers Merge también está diseñado para manejar la superposición de imágenes con desplazamientos negativos, 'cosiendo' ambas imágenes limpiamente. Aun así, necesito usar un "+repage" final para eliminar ese desplazamiento negativo de la imagen final, después de haberlas 'fusionado'. Si no lo hago, otros programas como los navegadores web podrían no entender tales desplazamientos negativos y producir efectos indefinidos. El ejemplo anterior también se ha colocado en el script de shell "[box_set_example](../static/img/scripts/box_set_example)", para que pueda descargarlo y experimentar con él más cómodamente. Puede llevar esto aún más lejos y añadir imágenes especulares de la 'caja' reflejadas por la superficie sobre la que se asienta, aunque tal vez también desee recolorear o atenuar esa imagen de algún modo para hacerla más realista. Consulte Reflections para tales técnicas de espejo.
Un ejemplo adicional en PHP se desarrolló en una discusión sobre cómo envolver 'fotos' alrededor de un marco de lienzo sin bordes. Consulte Canvas wrap transformation para más detalles.
Para terminar, aquí hay un ejemplo fantástico de Jean-François Hren para www.animecoversfan.com, que se discutió ampliamente en los foros de discusión de IM.

[Diagrama]

Esta imagen se creó tomando una imagen artística de la carátula de una caja de vídeo de anime, dividiendo esa carátula en 3 segmentos ('portada', 'lomo' y 'contraportada'), distorsionando cada uno por separado en imágenes en capas, añadiendo una cuarta imagen de 'disco' y fusionándolas. La imagen se remató luego con la adición de efectos de luces y sombras (mediante composición de imagen HardLight), y la adición de efectos de borde y sombra semitransparente (mediante CopyOpacity). Lo más asombroso es que todo el proceso se realizó con un único comando "magick", a partir de las imágenes de entrada. Es un excelente ejemplo de lo que IM puede hacer, y del proceso mediante el cual puede generarse un script de comandos complejo. Recomiendo leer la discusión del foro, ya que contiene muchas pistas, consejos y técnicas generales de depuración. (Se agradecen más ejemplos aportados)

Distorsión por proyección de perspectiva

Así como la distorsión '[Affine](#affine)' puede manejarse directamente dando los coeficientes matemáticos de una '[Affine Projection](#affine_projection)', también la '[Perspective](#perspective)' puede manejarse mediante 8 coeficientes de una distorsión 'Perspective Projection'. Como antes, estos números representan los coeficientes usados para el mapeo directo de los puntos de la imagen de origen a la imagen de destino. Es decir, son los valores matemáticos usados para mapear un x,y de la imagen de origen a un i,j de la imagen de destino. Los 8 argumentos de punto flotante son (en el orden indicado)... sx, ry, tx, rx, sy, ty, px, py


Estos valores de coeficiente forman a su vez la expresión.. Xd = | sx*Xs + ry*Ys + tx | , | Yd = | rx*Xs + sy*Ys + ty |
---|---|---|---|---|---


|


px*Xs + py*Ys + 1.0 | px*Xs + py*Ys + 1.0
Donde "Xs,Ys" son las coordenadas de la imagen de origen y "Xd,Yd" son las de la imagen de destino. Internamente, Distort de ImageMagick invertirá las ecuaciones anteriores para hacer el mapeo inverso de píxeles apropiado y así mapear las coordenadas "Xd,Yd" para buscar el color en "Xs,Ys" de la imagen de origen. Los primeros 6 valores de la 'Perspective Projection' son de hecho los mismos coeficientes que los de la '[Affine Projection](#affine_projection)', aunque están ligeramente reordenados para ser más lógicos (en términos de 'matemática matricial', los primeros 6 elementos se han transpuesto diagonalmente). Los dos argumentos adicionales px,py forman un divisor de escala para toda la distorsión, que hace que la imagen parezca más pequeña en la dirección concreta según los valores dados, otorgando así a la imagen distorsionada el efecto de 'distancia' en perspectiva. Si estos dos valores se ponen a cero, la distorsión 'Perspective Projection' se vuelve equivalente a una 'Affine Projection'. Por ejemplo... |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Perspective-Projection \
             '1.40, 0.25, 3.0    0.15, 1.30, 0.0    0.007, 0.009' \
          perspective_projection_rose.png

[IM Output]
Recuerde que la matriz que proporciona es la matriz proyectiva directa, que mapeará las coordenadas de la imagen de origen a las de la imagen de destino. Internamente, ImageMagick invertirá la matriz para poder mapear las coordenadas de la imagen de destino a las de la imagen de origen. Si desea ver cuáles son esos valores, use la opción de distorsión detallada para que IM emita sus coeficientes internos como una expresión del operador FX (véase a continuación).

Detalles internos de la perspectiva

Si añade "-verbose" (consulte Verbose Distortion Summery más arriba) justo antes de la distorsión de perspectiva, IM emitirá dos operadores que deberían ser reemplazos casi equivalentes del operador "-distort". Uno es una versión "-fx" MUY LENTA (consulte FX DIY operator). El otro será la matriz Perspective_Projection de mapeo directo. Por ejemplo... |

  magick rose: -alpha set -virtual-pixel transparent -verbose \
          -distort Perspective "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
          +verbose perspective_rose.png

[IM Output]
| [IM Text]


La primera sección, Perspective Projection , puede usarse para mapear las coordenadas de origen a coordenadas de destino. La fórmula es la anterior.

i = ( 1.430099*x +0.246650*y +3 )/( 0.006757*x + 0.009448*y +1 ) j = ( 0.147296*x +1.434591*y +0 )/( 0.006757*x + 0.009448*y +1 )


Un ejemplo de extracción y uso de estos valores se muestra en el último conjunto de ejemplos de Positioning Distorted Layer Images. Por otro lado, la segunda sección, el equivalente FX, usa un conjunto distinto de 8 coeficientes, que realiza el mapeo inverso de píxeles que una distorsión de imagen necesita aplicar en realidad. A saber...

x = ( 0.711858*i -0.108326*j -2.135575 )/(-0.004119*i -0.005877*j +1 ) y = (-0.073090*i +0.699571*j +0.219269 )/(-0.004119*i -0.005877*j +1 )


Observe que en la fórmula equivalente FX de salida los coeficientes del divisor se usan primero, ya que son comunes a las ecuaciones de coordenadas X e Y. Recuerde que todas las coordenadas que proporciona están en coordenadas de imagen, no en coordenadas de píxel; consulte Image Coordinates vs Pixel Coordinates para más detalles. Por ello, cualquier posición de píxel necesitará sumarle 0,5 a la coordenada de píxel de entrada antes de aplicar lo anterior, y luego restarle 0,5 a la coordenada final para devolverla a coordenadas de píxel (de dibujo). Puede ver esto aplicado en el código equivalente FX anterior. La comprobación final en el equivalente FX, justo antes de la búsqueda en la imagen de origen, maneja los píxeles 'de cielo' no válidos, donde el destino no logra mapearse correctamente a la imagen de origen. Sin embargo, simplemente sustituirá 'blue' por dichos píxeles en lugar de "-mattecolor", y no proporciona ningún suavizado del horizonte que el algoritmo interno sí aplica para la distorsión de perspectiva.
Ejemplo de mapeo directo de perspectiva... Estos mapeos le permiten llevar una coordenada concreta de una imagen a una posición de la otra (en cualquier dirección). Por ejemplo, un punto oscuro en el centro de la imagen de origen de la rosa está en las coordenadas de píxel '39,20'. Mapeándolo a coordenadas de imagen sumándole ½ obtenemos '39.5,20.5'. Ahora podemos usar las ecuaciones de x,y a i,j para mapearlo a coordenadas de la imagen de destino '44.2,24.1'. Y finalmente a coordenadas de píxel 'de dibujo' restando ½, con lo que obtenemos la posición final de '43.7,23.6'. Y aquí marco esa coordenada con un círculo tanto en la imagen de entrada como en la de salida..

  magick rose: -fill none -stroke black \
          -draw 'circle 39,20 39,24'    rose_marked.png

  magick perspective_rose.png -fill none -stroke black \
          -draw 'circle 43.7,23.6 43.7,26.6'  perspective_rose_marked.png

[IM Output] [IM Output]

Como puede ver, ¡el mismo punto de la imagen distorsionada en perspectiva se ha localizado correctamente en ambas imágenes (incluso a nivel subpíxel)!

Distorsiones bilineales

Los métodos de distorsión 'Bilinear' implementan otro tipo de distorsión de 4 puntos. Sin embargo, no es ni de lejos tan directa como la distorsión '[Perspective](#perspective)' que vimos arriba. Pero, como verá, es una distorsión alternativa muy útil.

Distorsión bilineal directa

Por ejemplo, tomemos una imagen de prueba especial de un mandril sobre la que se ha superpuesto una rejilla, y distorsionémosla con perspectiva y con bilineal.

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort Perspective \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_pers.jpg
  magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
       -distort BilinearForward \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_blin.jpg

[IM Output]
Original | | [IM Output]
Perspectiva | [IM Output]
Bilineal
---|---|---|---

Lo primero que debe notar es que ambas distorsiones mapearon correctamente la imagen de un conjunto de puntos de control al otro. Además, todas las líneas horizontales y verticales de la imagen de origen siguen siendo rectas en ambas distorsiones. Sin embargo, ahí terminan las similitudes. La perspectiva reduce el espaciado entre líneas de modo que incluso las líneas diagonales permanecen rectas. Esto hace que las áreas de los cuadrados se vuelvan más pequeñas, dando así a la esquina superior derecha un aspecto realista de 'estar a lo lejos'. La bilineal, en cambio, no hace que un lado de la imagen parezca 'más lejano', ni intenta mantener las líneas rectas. Lo que intenta es mantener constantes todos los espaciados entre las líneas, pero esto provoca que la línea diagonal se curve. Es decir, conserva las proporciones de distancia a lo largo de cualquier línea dada. Esto es, las longitudes relativas de cada segmento de línea permanecen iguales a lo largo de toda la longitud de la línea, aunque la línea en sí pueda quedar doblada, curvada o acortada en su conjunto. Esto significa que en el ejemplo anterior el espaciado de la rejilla mantiene una escala constante en toda la imagen, y el cuadrado distorsionado de la parte superior derecha sigue teniendo aproximadamente el mismo tamaño que el cuadrado distorsionado de la parte inferior izquierda. La imagen sigue teniendo un aspecto 'plano', simplemente distorsionada en una forma distinta. Tenga en cuenta que la bilineal (directa) sí garantiza que cualquier línea horizontal o vertical de la imagen original permanezca recta en la imagen final. Es decir, tomará un rectángulo alineado ortogonalmente y lo transformará en el cuadrilátero especificado, de modo que cada uno de los lados del rectángulo original permanezca recto con escala constante a lo largo de toda la línea. Es este aspecto de la distorsión lo que hace útil una distorsión 'BilinearForward' en distorsiones de 'rejilla' mucho más complejas. Es decir, porque dos 'cuadriláteros' vecinos, aunque puedan estar distorsionados de forma muy diferente, seguirán alineándose correctamente borde con borde. Aquí hay otra comparación entre '[Perspective](#perspective)' y '[BilinearForward](#bilinear_forward)', usando una distorsión muy severa de la imagen integrada de la rosa...

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Perspective "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
          perspective_rose.png
  magick rose: -alpha set -virtual-pixel transparent -interpolate Spline \
          -distort BilinearForward "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
          bilinear_rose.png

[IM Output]
Original | | [IM Output]
Perspectiva | [IM Output]
Bilineal
---|---|---|---

Para lograr sus objetivos (conservar todas las líneas rectas), la distorsión de perspectiva parece 'succionar' prácticamente toda la imagen hacia el área más pequeña de la derecha, mientras que la distorsión bilineal mantuvo la rosa centrada, centrada en su resultado. De nuevo, conservó las proporciones de distancia, manteniendo la rosa igualmente espaciada entre los bordes izquierdo y derecho. Todo lo que hizo fue simplemente comprimir verticalmente la altura de la imagen de forma lineal a lo largo de su longitud. Este aspecto de una distorsión 'BilinearForward' hace que también se la conozca como distorsión 'trapezoidal'. Es decir, simplemente comprime la imagen linealmente en una dirección, cuando solo se escala una dirección. Esa dirección de compresión puede incluso estar inclinada, en lugar de alineada con uno de los ejes. | _Tenga en cuenta que, debido a la complejidad del mapeo inverso de píxeles necesario para realizar una distorsión 'BilinearForward', el remuestreo de área está actualmente desactivado.

Por ello, las áreas de compresión extrema (más de un factor de 2) probablemente mostrarán algunos efectos de aliasing (vea los bordes de las líneas en los ejemplos anteriores). No obstante, puede usarse supermuestreo o '-interpolate Spline' para mejorar la calidad de la imagen final.
---|---
| _Antes de IM v6.5.7-0, la distorsión 'BilinearForward' aún estaba en desarrollo y tenía problemas con ciertos casos 'degenerados', que podían producir una imagen de error 'negra' en situaciones concretas.

---|---

Distorsión bilineal inversa

Dado que solo las líneas horizontales y verticales permanecen rectas, no se puede usar una distorsión 'BilinearForward para invertir la distorsión. Como las líneas de la rejilla de la imagen transformada ya no son horizontales ni verticales, ¡tampoco permanecerán rectas en la imagen resultante! Por ejemplo, intercambiar pares de coordenadas y volver a aplicar la distorsión 'directa' (como hicimos con la distorsión '[Perspective](#perspective)' más arriba) no logrará recuperar la imagen original.

  magick mandrill_blin.jpg -alpha set -virtual-pixel black \
       -distort BilinearForward \
              '26,0 0,0   114,23 128,0   128,100 128,128  0,123 0,128' \
       mandrill_blin_back.jpg

[IM Output] [IM Output]

Observe que las coordenadas especificadas sí se posicionaron correctamente, pero la distorsión de imagen no se invirtió. En resumen, una distorsión '[BilinearForward](#bilinear_forward)' NO es su propia inversa. Para restaurar la imagen necesita usar una distorsión ligeramente distinta pero estrechamente relacionada. La inversa matemática de la 'transformación geométrica' se ha implementado como la distorsión 'BilinearReverse'. Por ejemplo...

  magick mandrill_blin.jpg -alpha set -virtual-pixel black \
       -distort BilinearReverse \
              '26,0 0,0   114,23 128,0   128,100 128,128  0,123 0,128' \
       mandrill_blin_rev.jpg

[IM Output] [IM Output]

| Como ya se dijo, debido a la complejidad de una distorsión '[BilinearForward](#bilinear_forward)', el remuestreo de área está actualmente desactivado, lo cual en el caso anterior provoca efectos de aliasing severos.
---|---
La '[BilinearReverse](#bilinear_reverse)' tiene las mismas características de conservación de proporciones de distancia que una 'BilinearFoward', pero llevará cualquier cuadrilátero a un rectángulo alineado ortogonalmente, garantizando que los lados del cuadrilátero permanezcan rectos al mapearse a una alineación vertical y horizontal. Como puede ver arriba. | Antes de IM v6.5.1-2, la distorsión 'BilinearReverse' se implementaba simplemente como 'Bilinear'.
---|---
Algunas implementaciones de una distorsión bilineal (incluidas versiones antiguas de IM y la biblioteca Leptonica) solo implementaban la versión (inversa) más simple anterior de la distorsión bilineal. Sin embargo, tal distorsión no se adapta muy bien al 'mapeo directo' de una imagen rectangular. Por ejemplo, aquí intento usar una '[BilinearReverse](#bilinear_reverse)' para una distorsión que probablemente debería haber usado una distorsión '[BilinearForward](#bilinear_forward)'.

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort BilinearReverse \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_blin_rev2.jpg

[IM Output] [IM Output]

Como puede ver, dado que el cuadrilátero de destino no era un rectángulo ortogonal, la imagen quedó muy distorsionada, produciendo numerosas líneas curvadas hacia adentro.

Distorsiones bilineales teseladas

Ahora bien, aunque una '[BilinearReverse](#bilinear_reverse)' produce imágenes 'curvadas' a partir de rectangulares, el efecto sí produce patrones de teselas interesantes que parecen generar superficies curvas con aspecto tridimensional. Por ejemplo, aplicando la misma transformación que se usó en Visualización de horizontes lejanos más arriba, obtenemos este resultado interesante. |

  magick checks.png  -virtual-pixel tile  -mattecolor DodgerBlue \
          -distort BilinearReverse \
               '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          bilinear_rev_tile.png

[IM Output]
En realidad, '[BilinearReverse](#bilinear_reverse)' nunca producirá un 'horizonte' (píxeles no válidos). Por otro lado, usar '[BilinearForward](#bilinear_forward)' tiende a producir 'cielo' o 'píxeles no válidos' (rellenos con el "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" actual) con bastante regularidad. De hecho, el patrón de teselado tiende a volverse bastante caótico... |

  magick checks.png  -virtual-pixel tile  -mattecolor DodgerBlue \
          -interpolate Spline  -distort BilinearForward \
               '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          bilinear_fwd_tile.png

[IM Output]
| Como ya se dijo, debido a la complejidad de una distorsión '[BilinearForward](#bilinear_forward)', el remuestreo de área está actualmente desactivado, lo cual en el caso anterior provoca efectos de aliasing severos.
---|---
Por ello, no recomiendo usar una forma teselada de '[BilinearForward](#bilinear_forward)'. No obstante, sí recomiendo que defina un "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" apropiado al usar la distorsión directa, para evitar la aparición de inesperadas manchas grises de 'cielo'.

Detalles internos de la bilineal

La fórmula real para mapear una coordenada de la imagen de origen a una imagen de destino usando una distorsión bilineal de mapeo directo es... Xd = C0*Xs + C1*Ys + C2*Xs*Ys + C3 , Yd = C4*Xs + C5*Ys + C6*Xs*Ys + C7
Sin embargo, dado que IM implementa las distorsiones usando la técnica de mapeo inverso de píxeles, la fórmula anterior necesita invertirse. Un proceso complejo que requiere resolver una ecuación cuadrática, raíces cuadradas y una página entera de álgebra. Si pide a IM que emita de forma detallada el equivalente FX, verá esta complejidad. Por ejemplo, usando la imagen checks que creamos anteriormente...
  magick checks.png -alpha set -virtual-pixel transparent -mattecolor none \
      -interpolate Spline -verbose -distort BilinearForward \
                   '0,0,0,0  0,90,0,90  90,0,60,30  90,90,90,90' \
      +verbose bilinear_checks.png

[IM Output]
| [IM Text]


La comprobación '(rt > 0 ) ? red :' en la última línea del 'equivalente FX' sirve para evitar una raíz cuadrada negativa no válida. Esta es la comprobación que crea el efecto de 'cielo' mostrado en los ejemplos anteriores. Por otro lado, como la distorsión bilineal inversa es mucho más simple, puede aplicar directamente la ecuación polinómica más sencilla para invertir la distorsión anterior... |

  magick bilinear_checks.png  -virtual-pixel transparent \
      -verbose -distort BilinearReverse \
                   '0,0,0,0  0,90,0,90  60,30,90,0  90,90,90,90' \
      +verbose bilinear_checks_rev.png

[IM Output]
| [IM Text]


Como puede ver, las ecuaciones resultantes son muy simples, ya que ahora las aplicamos para hacer un mapeo inverso de píxeles de las coordenadas de destino a las coordenadas de la imagen de origen. Los efectos de aliasing que se ven arriba están provocados por '[BilinearForward](#bilinear_forward)', y no por la distorsión '[BilinearReverse](#bilinear_reverse)'. Esto se debe a que actualmente el remuestreo de área está desactivado para la versión de mapeo 'directo' debido a su complejidad.
Para profundizar más, le remito a Leptonica Affine and Perspective Transforms.

Distorsión bilineal combinada

En construcción

Los dos métodos de distorsión bilineal juntos le permitirán distorsionar directamente CUALQUIER cuadrilátero en cualquier otro cuadrilátero, manteniendo rectos los lados del cuadrilátero. En esencia, primero puede distorsionar 'a la inversa' un cuadrilátero en una imagen rectangular, y luego distorsionar 'directamente' ese rectángulo en el cuadrilátero final. Este tipo de distorsión también significa que puede tomar cualquier rejilla rectangular de coordenadas y distorsionarla en otra rejilla rectangular de coordenadas. Esto se conoce como distorsión de 'rejilla'. Esta técnica es la base principal del morphing de imágenes, donde se define una rejilla rectangular de líneas sobre dos imágenes y se usan para fusionar las imágenes en un compuesto intermedio, o incluso para generar una animación que transforma (morphing) correctamente una imagen en otra. Esto, sin embargo, aún no se ha implementado, aunque es una adición planificada.


Distorsión polinómica (distorsiona usando un ajuste polinómico)

La distorsión 'Polynomial', como la mayoría de los métodos de distorsión anteriores, también mapea pares de puntos de control, pero usa una ecuación polinómica estándar. Esto significa que se necesita un argumento adicional antes de proporcionar los puntos de control.

Order X1,Y1 I1,J1 X2,Y2 I2,J2 X3,Y3 I3,J3 X4,Y4 I4,J4 . . . .

El argumento 'Order ' suele ser un entero a partir de '1', aunque también puede usarse el valor especial '1.5'. Define el 'orden' o la complejidad de la ecuación matemática bidimensional (que usa tanto 'x' como 'y') que se aplicará. Por ejemplo, un polinomio de orden '1' ajustará una ecuación de la forma... Xd = | C2x*Xs + C1x*Ys + C0x | , | Yd = | C2y*Xs + C1y*Ys + C0y |
---|---|---|---|---|---
Que, si la compara con la ecuación usada para la proyección afín, verá que es equivalente. Como se necesitan 3 constantes para cada fórmula X e Y, también debe proporcionar al menos 3 pares de coordenadas X,Y. Cualquier número adicional hará que la ecuación se ajuste por mínimos cuadrados a las coordenadas dadas. El siguiente 'orden', '1.5', es equivalente a una '[BilinearReverse](#bilinear_reverse)' (recuerde que la ecuación se usa para mapear las coordenadas de destino a la imagen de origen). Xd = | C3x*Xs*Ys + C2x*Xs + C1x*Ys + C0x | , | Yd = | C3x*Xs*Ys + C2y*Xs + C1y*Ys + C0y |
---|---|---|---|---|---
Al igual que la distorsión '[BilinearReverse](#bilinear_reverse)', necesita un mínimo de 4 coordenadas. Por ejemplo... Básicamente, esto es exactamente lo mismo que las ecuaciones de orden '1', pero con 1 término adicional añadido a las ecuaciones polinómicas. Es decir, como cada ecuación tiene ahora 4 términos por eje, con 4 constantes, ahora necesita al menos 4 pares de coordenadas para que IM pueda determinar dichas constantes.

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort Polynomial \
              '1.5   0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_poly_1.5.jpg

[IM Output] [IM Output]

Con un orden '2', las ecuaciones polinómicas se amplían aún más para convertirse en un ajuste cuadrático completo, que requiere un mínimo de al menos 6 pares de coordenadas. Xd = C5x*Xs2 + C4x*Xs*Ys + C3x*Ys2 + C2x*Xs + C1x*Ys + C0x
Yd = C5y*Xs2 + C4y*Xs*Ys + C3y*Ys2 + C2y*Xs + C1y*Ys + C0y
Básicamente, esto es exactamente lo mismo que las ecuaciones de orden '1', pero con 3 términos adicionales (orden 2 + 1) antepuestos a las ecuaciones polinómicas. Es decir, como cada ecuación tiene ahora 6 términos con 6 constantes, ahora necesita al menos 6 coordenadas para que IM pueda determinar dichas constantes. Cada orden de polinomio sucesivo a partir de este añade otros 'orden'+1 términos a cada una del par de ecuaciones. Por ello, un polinomio de ajuste cúbico de orden '3' requiere un mínimo de 10 pares de coordenadas para quedar totalmente definido, y un polinomio de ajuste quíntico de orden '4' necesita 15 pares de coordenadas. Puede usar un resumen de distorsión detallado para ver la ecuación resultante que la distorsión polinómica ajustó a las coordenadas especificadas. Como ejemplo más grande, tengo una imagen de una rejilla. También tengo un amplio conjunto de coordenadas (almacenadas en el archivo "[grid16_control_points.txt](../static/img/images/grid16_control_points.txt)") sobre cómo quiero deformar esa rejilla. Luego pedí a IM que generara un polinomio cúbico para 'ajustar de la mejor forma' las coordenadas de entrada.
  # warp image
  magick grid16.png -virtual-pixel gray \
          -distort polynomial "3 $(cat grid16_control_points.txt)" \
          grid16_polynomial.png

  # reverse image coordinate order
  awk '{print $3, $4, $1, $2}' grid16_control_points.txt \
                             > grid16_cp_inverse.txt

  # warp image back again
  magick grid16_polynomial.png -virtual-pixel gray \
          -distort polynomial "3 $(cat grid16_cp_inverse.txt)" \
          grid16_restored.png

[IM Output] [IM Output] [IM Output]

El pequeño script "awk" toma el conjunto original de pares de puntos de control X,Y e invierte su orden, de modo que podemos usar el nuevo archivo para intentar 'deshacer' la distorsión. | _Las coordenadas del archivo de puntos de control "[grid16_control_points.txt](../static/img/images/grid16_control_points.txt)" están en coordenadas de imagen, lo que significa que cada número se refiere al centro del píxel correspondiente. Sin el 0.5 adicional, los valores estarían en 'coordenadas de píxel' enteras. Consulte Coordenadas de imagen frente a coordenadas de píxel más arriba.

Los valores se determinaron puramente a mano mediante consulta visual con un visor de imágenes y, como tal, no son realmente muy exactos. Esto podría ser el origen de algunos artefactos de la distorsión inversa, aunque el 'mejor ajuste' funcional de las ecuaciones polinómicas habría reducido los efectos generales de distorsión.


---|---
Esto muestra que, aunque una distorsión polinómica funciona, y funciona bien, no es una distorsión exacta ni reversible. En esencia, las 81 coordenadas se 'promedian' juntas para generar un 'mejor ajuste' matemático de las coordenadas de entrada. Dado que se han proporcionado más puntos de control (81) que el mínimo (10) necesario, no se garantiza que ninguno de los puntos de control coincida exactamente con las coordenadas solicitadas. Sin embargo, para este ejemplo concreto, en el que las coordenadas están cerca del resultado distorsionado esperado, el ajuste debería ser razonablemente próximo. La función polinómica suele tener más errores a lo largo de los bordes y, especialmente, en las esquinas de la imagen. Esto no solo afecta a la ubicación de los píxeles, sino también al área de muestreo (EWA) en los bordes. Es un resultado natural de la aproximación empleada. Podría haberse usado un polinomio de orden superior, pero en este caso no aporta grandes mejoras. Para este caso concreto, el polinomio está intentando ajustarse a una función trigonométrica no polinómica. Debido a la naturaleza de esas funciones, la segunda distorsión será más inexacta que la primera. Este ejemplo está, en realidad, muy relacionado con un método radial de Distorsión de barril que veremos más abajo. Observe, no obstante, que las coordenadas que se mapean no necesitan estar dispuestas en una cuadrícula, sino que pueden ser cualquier conjunto de mapeo de coordenadas. Por ello suele emplearse en geografía para alinear (y superponer) fotos aéreas con mapas geofísicos, usando como puntos de control ubicaciones conocidas de pueblos, cruces de caminos, picos de montañas y otros hitos. | _Dado que la Distorsión polinómica es generalmente no reversible, IM no puede calcular el 'mejor ajuste' del viewport de la imagen de destino para la imagen de origen dada. Por ello, la forma "[+distort](#distort_bestfit)" del operador no funciona y recurre a una operación "[-distort](https://imagemagick.org/command-line-options/#distort)" normal. No obstante, aún puede usar la opción Viewport de distorsión para definir el viewport de la imagen de destino.

---|---


Métodos de distorsión circular y radial

Estas son distorsiones que utilizan vectores radiales como componente principal del proceso de distorsión.

Distorsión Arc (curvar imágenes en arcos circulares)

La distorsión 'Arc' (a partir de IM v6.3.5-5) es una variación simple de una distorsión mucho más compleja, la distorsión polar (véase más abajo). De forma predeterminada, curva la imagen dada en un arco perfectamente circular sobre el ángulo indicado y, sin otros argumentos, intentará preservar en la medida de lo posible tanto la escala de la línea central horizontal de la imagen como la relación de aspecto de esta. Para ello admite hasta cuatro argumentos.

_arc_angle rotate_angle top_radius bottom_radius_

Sin embargo, solo el "_arc_angle_" es obligatorio; los demás argumentos son opcionales y pueden añadirse según sea necesario, en el orden indicado. Por ejemplo, aplicar 'Arc' a una imagen sobre un ángulo de 60 grados... |

  magick rose: -virtual-pixel White -distort Arc 60  arc_rose.jpg

[IM Output]
| _Tenga en cuenta que, a diferencia de los demás operadores de distorsión de imágenes, una distorsión 'Arc' siempre ajustará el tamaño de la imagen resultante para que la imagen de origen completa esté presente. Esto incluye cualquier píxel de borde con antialiasing. Por ello, la imagen resultante rara vez coincidirá con el tamaño de la imagen de entrada.

Solo las Opciones de viewport de distorsión le permitirán cambiar el tamaño de la imagen resultante para una distorsión concreta._
---|---
Añadir el segundo argumento "_rotate_agle_" le permite rotar la imagen alrededor del círculo. Por ejemplo, rotarla 90 grados. |

  magick rose: -virtual-pixel White -distort Arc '60 90'  arc_rose_rot.jpg

[IM Output]
Como no se ha indicado ningún argumento de radio específico, el método de distorsión 'Arc' se esfuerza al máximo por preservar la escala de la imagen original en la medida de lo posible. Para ello, la línea central horizontal de la imagen se establece en el 'radio ideal' correspondiente al ancho y al "_arc_angle_" indicado de la imagen de origen. Esto significa que si arquea la imagen sobre un "_arc_angle_" mayor, el radio de la línea central usada también se reducirá en el mismo factor. Así, el radio de la línea central será más pequeño y cerrado. |

  magick rose: -virtual-pixel White -distort Arc 120  arc_rose_3.jpg

[IM Output]
Observe cómo la imagen ahora cabe en un círculo más pequeño, ¡pero el borde inferior de la imagen forma un círculo aún más pequeño! Si establece un ángulo de arqueado todavía mayor, el borde inferior alcanzará el centro de la distorsión, y más allá, lo que provoca que la parte inferior de la imagen de origen desaparezca en el olvido.

  magick rose: -virtual-pixel White -distort Arc 60   arc_rose_1.jpg
  magick rose: -virtual-pixel White -distort Arc 90   arc_rose_2.jpg
  magick rose: -virtual-pixel White -distort Arc 120  arc_rose_3.jpg
  magick rose: -virtual-pixel White -distort Arc 180  arc_rose_4.jpg
  magick rose: -virtual-pixel White -distort Arc 240  arc_rose_5.jpg
  magick rose: -virtual-pixel White -distort Arc 300  arc_rose_6.jpg
  magick rose: -virtual-pixel White -distort Arc 360  arc_rose_7.jpg

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Arc hasta formar anillos circulares completos

Las imágenes más largas se distorsionan con 'Arc' mucho mejor sobre ángulos muy grandes. Por ejemplo, puede envolver imágenes largas (como mensajes de texto) en anillos. Y para que pueda ver realmente lo que ocurre, establecí un color de fondo de Píxel virtual distinto, de modo que pueda apreciar el límite de la imagen original.

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 60     arc_circle_1.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 120    arc_circle_2.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 180    arc_circle_3.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 270    arc_circle_4.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 360    arc_circle_5.jpg

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Y, ¡abracadabra!, hemos arqueado la imagen de la etiqueta en un círculo completo. Si observa de cerca la unión de la imagen del círculo completo, puede que vea una pequeña línea de píxeles donde la unión no queda del todo terminada. Esto lo causa el efecto del fondo de Píxel virtual 'SkyBlue' circundante, ya que en realidad estamos uniendo dos bordes de una imagen. Al generar un círculo completo, necesita usar un método de píxel virtual que 'una' estos dos bordes correctamente. Esto se consigue normalmente usando uno de los métodos de Píxel virtual en mosaico, como Tile. |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Tile -background SkyBlue \
          -distort Arc 360   arc_circle_tile.jpg

[IM Output]
Lamentablemente, como puede ver, esto no solo une la imagen correctamente, sino que también genera líneas duplicadas de la imagen hacia dentro y hacia fuera del anillo principal. Nada bueno. A partir de IM v6.4.2-6, un nuevo método de Píxel virtual, HorizontalTile, resuelve este problema. Este método repite la imagen en mosaico solo lateralmente, por lo que crea una buena unión para nuestra imagen circular, pero rellena las áreas por encima y por debajo de los mosaicos con el color de fondo actual, produciendo un círculo de texto perfecto. |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc 360   arc_circle.jpg

[IM Output]
Si, antes de arquear una imagen, la rota boca abajo, puede colocar la parte 'superior' original de la imagen en el borde interior del círculo. Por supuesto, puede que quiera 'rotar' el resultado de nuevo hacia arriba al terminar, pero esa capacidad ya está incorporada en el método de distorsión 'Arc'. |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background -background SkyBlue \
          -rotate 180 -distort Arc '270 180'  arc_flip.jpg

[IM Output]
El tercer argumento "_top_radius_" anulará el radio 'ideal' de la línea central que se calcula, de modo que la parte superior de la imagen se convierta en un círculo del radio indicado. Esto crea un anillo de 100 píxeles de ancho, aunque la imagen que lo acomoda es de 102 píxeles de ancho para dejar espacio a los efectos de antialiasing. |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc '360 0 50'  arc_radius.jpg

[IM Output]
La imagen sigue manteniendo la misma relación de aspecto, por lo que el resultado anterior es esencialmente el mismo que antes, solo que escalado para que quepa en el círculo del radio solicitado. Recuerde que el radio puede ser de punto flotante, pero el centro de un arco siempre se alineará con una 'esquina' de píxel, por lo que la imagen resultante seguirá teniendo un número par de píxeles de ancho. Si proporciona el cuarto argumento "_bottom_radius_", puede tener control completo sobre el ancho del anillo, o su 'altura radial'. |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc '360 0 45 30'   arc_inner.jpg

[IM Output]
Esto distorsionará la escala radial de la imagen y, en efecto, separa la escala radial del 'ancho del arco' o ángulo de la imagen resultante. En otras palabras, la relación de aspecto original de la imagen ya no se preservará. Incluso puede forzarla a llenar por completo el interior del círculo, envolviendo el borde inferior de la imagen de entrada en el centro, o 'polo', de la distorsión. |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc '360 0 45 0'   arc_fill.jpg

[IM Output]

Ejemplos de distorsión Arc

Puede generar efectos interesantes usando una Distorsión Arc; por ejemplo, arquear un patrón de tablero de ajedrez alargado en el anillo (usando el ajuste de Píxel virtual '[HorizontalTile](misc.html#horizontal_tile)') produce... |

  magick -size 210x30 pattern:checkerboard -alpha set \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc 360   arc_checks.png

[IM Output]
Usando el ajuste predeterminado de Píxel virtual '[Edge](misc.html#edge)', puede producir un efecto más interesante. |

  magick -size 210x30 pattern:checkerboard  -virtual-pixel Edge \
          -distort Arc 360   arc_checks_edge.png

[IM Output]
Por supuesto, un ajuste '[Tile](misc.html#edge)' también generó efectos 'radiales' interesantes, permitiéndole generar un patrón de tablero de ajedrez circular. |

  magick -size 210x30 pattern:checkerboard  -virtual-pixel Tile \
          -distort Arc 360   arc_checks_tile.png

[IM Output]
Lo anterior puede refinarse aún más controlando el radio superior e inferior de la imagen resultante. Aquí tiene algunos ejemplos más de distorsión '[Arc](#arc)', pero le dejo que juegue con ellos para descubrir cómo funcionan. ¿Qué se le ocurre? |

  magick -size 90x1 pattern:gray50 -scale 900x100 -normalize \
          -virtual-pixel Tile  -set option:distort:viewport 100x100-50-50 \
          -distort Arc 360  +repage  arc_radii.gif

[IM Output]
|

  magick -size 400x100 pattern:hs_diagcross \
          -virtual-pixel Tile  -set option:distort:viewport 100x100-50-50 \
          -distort Arc '360 0 80 0' +repage  arc_cross.gif

[IM Output]
|

  magick -size 360x80 xc: -draw "fill none stroke black line 0,5 360,80" \
          -virtual-pixel White  -distort Arc '360 0 50 0'  arc_spiral.gif

[IM Output]

|

  magick tree.gif -set option:distort:viewport 120x60-60-60 \
          -virtual-pixel Dither  +distort Arc '180 0 25 0' \
          +repage arc_rays.gif

[IM Output]
Los 'rayos' de este último ejemplo son un subproducto del ajuste de Píxel virtual pseudoaleatorio '[Dither](misc.html#dither)', que produce un patrón de píxeles extraño del color del 'sol' procedente de la esquina superior izquierda de la imagen original. Los mismos efectos de tramado también producen la línea circular de 'guiones' que rodea la imagen del 'árbol'. Puede lograr una versión similar y más controlada de este efecto usando un ajuste '[Edge](misc.html#edge)' con una imagen que se haya modificado para añadir píxeles de borde interesantes.

Colocación del punto central del Arc

De forma predeterminada, '[Arc](#arc)' ignorará por completo cualquier desplazamiento de Lienzo virtual que pueda tener la imagen, e incluso no informará de la ubicación del 'centro' alrededor del cual se arqueó la imagen. Sin embargo, conocer la ubicación del 'punto central' puede ser muy útil. Si en lugar de usar "-distort" usa la forma especial con signo más, "+distort", se asignará a la imagen un Lienzo virtual, de modo que el centro quede situado en el origen del lienzo virtual. En otras palabras, el punto '0,0' de la imagen se establece como el 'centro' del arco. Esto resulta especialmente útil para posicionar una imagen arqueada con un ángulo menor que el círculo completo, donde el 'centro' del arco no es el centro de la imagen. Por ejemplo... |

  magick logo: -resize x150 -gravity NorthEast -crop 100x100+10+0! \
          \( -background none label:'IM Examples' \
             -virtual-pixel Background +distort Arc '270 50 20' \
             -repage +75+21\! \)  -flatten  arc_overlay.jpg

[IM Output]
Aquí creo una etiqueta de texto y la distorsiono con '[Arc](#arc)' formando un círculo incompleto usando la forma con signo más "+distort" del operador. IM preservó cuidadosamente el 'centro' del arco mediante el desplazamiento del lienzo virtual de la imagen. Esto significa que, simplemente realizando un ajuste relativo del desplazamiento con "-repage" y un indicador '!', podemos posicionar el círculo de texto resultante donde queramos. Por ejemplo, la punta del sombrero del mago, que se ubica en la coordenada de píxel 75,21 en el ejemplo anterior. Lamentablemente, como se usan desplazamientos virtuales para posicionar la imagen, el posicionamiento exacto está limitado a tamaños de píxel enteros. No puede posicionar una Distorsión Arc en una ubicación definida con subpíxeles sin realizar una segunda distorsión. Sin embargo, sí puede hacerlo con una Distorsión polar (véase a continuación).

Distorsión Polar (distorsiones en círculo completo)

La distorsión 'Polar' (añadida en IM v6.4.2-6) es una versión de más bajo nivel de la distorsión '[Arc](#arc)' anterior. Pero no realiza automáticamente el 'bestfit', ni intenta preservar las relaciones de aspecto de las imágenes. Los 6 argumentos opcionales de punto flotante son... Radius_Max Radius_Min Center_X,Center_Y Start_Angle,End_Angle

Todos los argumentos son opcionales en sus posiciones separadas por espacios. De forma predeterminada, 'CenterX,Y ' tomará como valor el centro exacto del área de la imagen de entrada. Luego se generará una imagen polar en círculo completo de modo que todo el borde superior se convierte en el centro, mientras que el borde inferior se envuelve por completo alrededor del exterior del círculo. Los bordes izquierdo y derecho se encontrarán por encima del punto central, en los ángulos '-180' a '+180' de la imagen. Como debe indicarse 'Radius_Max ', este debería tener algún valor positivo. Sin embargo, si proporciona un valor de '0', se establecerá en la distancia entre el centro y el borde más cercano, de modo que, si no se dan los demás valores (predeterminados), toda la imagen de entrada se mapea en un círculo en el centro de la imagen. Por ejemplo, mapeemos un mapa del mundo en una vista polar, usando todos los valores predeterminados. Por supuesto, debería especificar un ajuste de Píxel virtual '[HorizontalTile](misc.html#horizontal_tile)' al producir un mapeo polar de círculo completo...

  magick worldmap_sm.jpg -virtual-pixel HorizontalTile  \
          -background Black   -distort Polar 0   polar_arctic.jpg

[IM Output] [IM Output]

Por supuesto, esto distorsiona el hemisferio sur severamente, envolviendo la Antártida por completo alrededor de la circunferencia del 'mundo-disco'. Rotando la imagen de origen y recortándola para mostrar solo el casquete polar, podemos generar un buen mapa del continente antártico. También especifiqué un radio de salida mayor para hacerlo más visible y pedí a IM que 'ajustara' la imagen de salida a ese tamaño usando la forma con 'signo más' del Operador de distorsión. |

  magick worldmap_md.jpg -rotate 180 -crop 100%x25%+0+0 +repage \
          -virtual-pixel HorizontalTile -background Black \
          +distort Polar 80 +repage  polar_antarctica.jpg

[IM Output]
Tenga en cuenta que lo anterior no son vistas estrictamente correctas de la Tierra, ya que el mapa cartesiano es una representación de una esfera, y no una imagen en coordenadas polares. Si usa un valor especial de 'Radius_Max ' de exactamente '-1', el radio de la imagen distorsionada se establece en la distancia desde el centro hasta la esquina más lejana (diagonal). Esto proporciona una 'inversa' ideal para una distorsión '[DePolar](#depolar)' de imagen completa, que veremos a continuación. (Véase Trucos (De)Polar más abajo para ejemplos de uso). | Recuerde que, a diferencia de una distorsión '[Arc](#arc)', '[Polar](#polar)' (también conocida como distorsión 'cartesiana a polar') no intenta preservar la relación de aspecto 'ideal' de la imagen de origen. Se aconseja precaución.
---|---
Los argumentos 'CenterX,Y ' son más útiles para posicionar el centro de la imagen resultante en un desplazamiento de subpíxel. Es decir, si el centro está en el límite de un píxel (número entero) o en el centro de un píxel (con desplazamientos de 0.5). Por supuesto, también determina la ubicación de la 'capa' del lienzo virtual. Sin embargo, de forma predeterminada se le asigna como valor el centro de la imagen (para "-distort", que usa la imagen de entrada como viewport) o 0,0 (para la imagen de capa "+distort"). Los siguientes argumentos 'Start_Angle,End_Angle son aún menos usados, y limitan los ángulos que cubre la imagen de entrada, con un valor predeterminado de -180 a 180 grados (0 es directamente hacia abajo). Al igual que con la distorsión '[Arc](#arc)', podría usar esto para rotar la imagen polar resultante. Pero también puede emplearse para generar 'arcos'. Por ejemplo...

  magick worldmap_sm.jpg -virtual-pixel Black -background Black \
          +distort Polar  '60,20 0,0 -60,60' +repage  polar_arc.jpg

[IM Output] [IM Output]

Tenga en cuenta que, actualmente, IM no reduce el tamaño de la imagen de capa resultante, que se alinea de modo que el origen de la imagen virtual quede en las coordenadas 0,0, como se solicitó. Aparte del estilo de los argumentos, esta es la mayor diferencia entre la distorsión '[Arc](#arc)' y '[Polar](#polar)'. Observe también que el borde izquierdo (ángulo -60) está a la izquierda. Esto es matemáticamente correcto si se tiene en cuenta que el eje 'Y' es descendente (igual que para todas las rotaciones de imagen). Por supuesto, como con Arc, puede usar efectos de mosaico de píxel virtual para generar patrones repetidos. Por ejemplo, este es exactamente igual que el último ejemplo, solo que con un ajuste '[HorizontalTileEdge](misc.html#horizontal_tile)'... |

  magick worldmap_sm.jpg -virtual-pixel HorizontalTile -background Black \
          +distort Polar  '60,20 0,0 -60,60' +repage  polar_arc_tiled.jpg

[IM Output]

Distorsión DePolar (polar a cartesiano)

Esta es, en esencia, la inversa de una distorsión '[Polar](#polar)', y tiene exactamente el mismo conjunto de argumentos opcionales. Los 6 argumentos opcionales de punto flotante son...

Radius_Max Radius_Min Center_X,Center_Y Start_Angle,End_Angle

De nuevo, si 'Radius_Max ' se establece en '0', se usa la distancia de 'CenterX,Y ' al borde más cercano, lo que significa que todo lo que esté dentro del círculo entero más grande se mapeará para encajar en una imagen del mismo tamaño que la de entrada. Por ejemplo, invirtamos el anterior 'mundo-disco' de nuevo a un mapa cartesiano.

  magick polar_arctic.jpg  -distort DePolar 0  world_restored.jpg

[IM Output] [IM Output]

Como el tamaño de la imagen de entrada se ha preservado a lo largo de las dos distorsiones, el resultado anterior es básicamente idéntico al mapa original. Por supuesto, como la imagen se comprimió tanto en el 'polo' superior como en el radio, la salida es bastante más borrosa de lo que cabría esperar. En realidad, esto empeora por el hecho de que el algoritmo de Remuestreo de área (EWA) no puede muestrear píxeles en un arco circular. Por ello, el Remuestreo de área se desactiva para las distorsiones "[DePolar](#depolar)". Se recomienda usar en su lugar alguna forma de técnica de Supermuestreo, como la que se muestra en la siguiente sección.
Si permite que IM use 'bestfit' (mediante la forma "+distort" del operador), redimensionará la imagen de salida para mantener 'Radius_Max ' a escala unitaria, y establecerá el ancho en la distancia de la circunferencia del radio situado a medio camino entre 'Radius_Max ' y 'Radius_Min '. Esto intenta, en esencia, preservar lo mejor posible la relación de aspecto de la imagen polar, aunque puede producir una imagen más larga y delgada de lo esperado. Por ejemplo.
  magick polar_arctic.jpg  +distort DePolar 0  world_restored_2.jpg

[IM Output] [IM Output]

Trucos del ciclo (De)Polar (desenfoques radiales/angulares)

Como vimos antes, usar un 'Radius_Max ' de '0' garantizará que toda la imagen se mapee en un círculo al usar una distorsión '[Polar](#polar)' (cartesiana a polar), y el mismo ajuste mapeará ese círculo de vuelta a una imagen rectangular mediante '[DePolar](#depolar)' (polar a cartesiana). Sin embargo, esto no funcionará muy bien si lo que quiere es aplicar '[DePolar](#depolar)' a una imagen rectangular y luego invertir la distorsión de nuevo con '[Polar](#polar)'. Por ejemplo, tomemos una imagen de una flor, apliquemos de-polar y luego restaurémosla con el valor especial de 'Radius_Max ' de '0' (radio = borde más cercano).

  magick flower_sm.jpg -virtual-pixel Black \
          -distort DePolar 0  flower_depolar.jpg
  magick flower_depolar.jpg \
          -virtual-pixel HorizontalTile -background black \
          -distort  Polar  0  flower_circle.jpg

[IM Output] [IM Output] [IM Output]

Ahora la imagen no se restaura correctamente, ya que quedó recortada por la primera distorsión '[DePolar](#depolar)'. Aun así, esta es en sí misma una técnica útil, y puede usarse para generar máscaras circulares perfectas para una imagen existente, dimensionadas de un modo completamente independiente de la imagen de entrada dada. Para realizar esta técnica del ciclo '[DePolar](#depolar)'-'[Polar](#polar)' correctamente, necesitamos usar un radio que sea la distancia desde el centro hasta la esquina más lejana. El valor especial de 'Radius_Max ' de '-1' pedirá a IM que calcule y use la esquina más lejana del 'punto central' como radio.

  magick flower_sm.jpg  -virtual-pixel Black \
          -distort DePolar -1  flower_depolar-1.jpg
  magick flower_depolar-1.jpg \
          -virtual-pixel HorizontalTile -background black \
          -distort  Polar  -1  flower_restored.jpg

[IM Output] [IM Output] [IM Output]

La imagen restaurada está ligeramente borrosa, lo que se debe a la compresión del radio necesaria para preservar toda la imagen durante la operación '[DePolar](#depolar)'. Eso, no obstante, puede corregirse usando una técnica apropiada de Supermuestreo (véase el siguiente conjunto de ejemplos). Pero ¿por qué querría convertir una imagen a esta forma y de vuelta? Pues bien, aplicando otras distorsiones a la versión 'DePolar' intermedia de la imagen, puede generar efectos radiales o angulares muy elaborados con gran facilidad. Por ejemplo, desplazando la imagen intermedia con 'roll', rotará la imagen de salida, aunque puede que obtenga algo de recorte en las esquinas... |

  magick flower_sm.jpg -virtual-pixel Black -distort DePolar -1 \
          -roll +15+0 \
          -virtual-pixel HorizontalTile -background Black \
          -distort  Polar  -1  flower_polar_rotate.jpg

[IM Output]
Tenga en cuenta que la dirección de la rotación es inversa a la del Operador Rotate o la Distorsión SRT.

Problemas del ciclo Depolar-Polar

En la rotación de imagen anterior puede que haya notado algunas distorsiones tipo 'escalera' a lo largo del borde de la imagen rotada. Este es un problema bien conocido, y lo causa la compresión de la gran circunferencia circular de la imagen en el 'ancho' más pequeño de la imagen de entrada. Por ejemplo, aquí tomo la imagen de prueba del tablero de ajedrez y simplemente la paso por un ciclo Depolar-Polar normal sin realizar ningún cambio.

  magick checks.png   -virtual-pixel Transparent \
          -distort DePolar -1   checks_depolar.png
  magick checks_depolar.png  -virtual-pixel HorizontalTile -background None \
          -distort  Polar  -1   checks_cycled.png

[IM Output] [IM Output] [IM Output]

Puede ver con claridad los efectos de aliasing causados por la compresión de la imagen en las puntas de la imagen intermedia. También se agrava por el hecho de que el Remuestreo de área normal no se usa durante esa conversión '[Depolar](#depolar)' inicial de la imagen de entrada. La mejor manera de resolver este problema es usar el Escalado de salida de distorsión para, a la vez, ampliar la imagen intermedia y luego reducir la imagen final. Esto proporcionará un resultado con Supermuestreo, que eliminará los artefactos de compresión vistos arriba. Por ejemplo, este es el mejor ciclo depolar-polar 'sin operación', todo en un solo comando... |

  magick checks.png -virtual-pixel Background -background None \
          -set option:distort:scale 4  -distort DePolar -1 \
          -noop \
          -virtual-pixel HorizontalTile -background None \
          -set option:distort:scale .25 -distort  Polar  -1 \
          checks_cycled_ss.png

[IM Output]
Como puede ver, los horribles efectos de aliasing prácticamente han desaparecido. No obstante, tenga cuidado: una imagen muy alta y delgada podría hacer reaparecer el problema. Lo mejor es limitar esto a imágenes 'apaisadas' o anchas, con supermuestreo como se muestra arriba. Lo único que necesita hacer ahora es reemplazar el operador "-noop" con el comando apropiado para generar el efecto radial y rotacional que busca.

Ejemplo de efectos Depolar-Polar

Así que mostremos de nuevo una mejor rotación polar de la imagen, esta vez usando supermuestreo. Tenga en cuenta, no obstante, que como la imagen intermedia es 4 veces mayor, la cantidad de Roll de imagen también debe ser 4 veces mayor. |

  magick flower_sm.jpg   -virtual-pixel Black \
          -set option:distort:scale 4   -distort DePolar -1 \
          -roll +60+0   \
          -virtual-pixel HorizontalTile -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_polar_rotate_ss.jpg

[IM Output]
Como puede ver, el efecto de 'escalera' a lo largo del borde se ha eliminado, con un resultado de imagen de calidad mucho mayor.
O bien puede aplicar un desenfoque lineal simple de la imagen intermedia (como el que se logra comprimiendo y ampliando de nuevo la imagen). |

  magick flower_sm.jpg -virtual-pixel Black \
          -set option:distort:scale 4   -distort DePolar -1 \
          -scale 10%x100%\! -filter Gaussian -resize 1000%x100%\! +filter \
          -virtual-pixel HorizontalTile -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_angular_blur.jpg

[IM Output]
El resultado es muy similar a un 'desenfoque rotacional' de la imagen. Esto se parece, pero no es exactamente igual, al mal llamado Operador de desenfoque radial. En realidad, los resultados son de mayor calidad que ese método de desenfoque especializado. Observe que el uso de un color 'black' en las diversas formas de Ajustes de píxel virtual aplicadas provocará un ligero oscurecimiento de los bordes, pero no es demasiado malo en el caso anterior. Un método para eliminar los efectos de bordes 'negros' sería usar en su lugar el color 'transparency' y luego, al terminar, desactivar por completo el canal alfa para dejar solo el color real que IM calculó. Otro es usar dos métodos de píxel virtual de 'borde' ('[Edge](misc.html#edge)' y '[HorizontalTileEdge](misc.html#horizontal_edge)'), que extienden los bordes de la imagen hacia el espacio indefinido del lienzo virtual. |

  magick flower_sm.jpg -virtual-pixel Edge \
          -set option:distort:scale 4   -distort DePolar -1 \
          -scale 10%x100%\! -filter Gaussian -resize 1000%x100%\! +filter \
          -virtual-pixel HorizontalTileEdge -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_angular_blur_edge.jpg

[IM Output]
Lo cual muestra un resultado mucho mejor cerca de los bordes.
Al desenfocar la versión polar de la imagen verticalmente, esta vez usando el Operador de desenfoque de movimiento en lugar de la compresión por redimensionado, puede generar unas estrías radiales que se desplazan hacia fuera desde el centro de la imagen... |

  magick flower_sm.jpg   -virtual-pixel Black \
          -set option:distort:scale 4   -distort DePolar -1 \
          -virtual-pixel Edge   -motion-blur 0x28-90 \
          -virtual-pixel HorizontalTile -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_radial_blur.jpg

[IM Output]
Para que el resultado solo desenfoque las zonas claras (los pétalos) de la imagen, puede componer esto con la imagen original usando Lighten, de modo que solo permanezcan visibles los colores más claros desenfocados, sin que los colores oscuros se desenfoquen hacia las áreas más claras y destruyan las manchas amarillas del centro de la flor. |

  magick flower_sm.jpg  flower_radial_blur.jpg \
          -compose Lighten -composite   flower_radial_blur_lighten.jpg

[IM Output]
Véase también Estrellas y cometas para otro ejemplo de cómo hacer esto, pero generando directamente la imagen 'DePolar' intermedia antes de aplicar una distorsión '[Polar](#polar)'. Un agradecimiento especial a Fred Weinhaus por los usos especiales de un ciclo DePolar-Polar y por insistir en que me asegurara de que estas distorsiones fueran totalmente reversibles para imágenes rectangulares. Él aprovecha bien esta técnica en varios de sus scripts de ImageMagick, entre ellos "[bump](http://www.fmwconcepts.com/imagemagick/bump/index.php)", "[ripples](http://www.fmwconcepts.com/imagemagick/ripples/index.php)" y "[striations](http://www.fmwconcepts.com/imagemagick/striations/index.php)".

Distorsión de barril (corrección de distorsiones de lente)

La distorsión de barril (añadida en IM v6.4.2-4) está diseñada específicamente para corregir las distorsiones esféricas causadas por las lentes de las cámaras en las fotos. Es decir, distorsiones como los efectos de barril y de cojín, que son efectivamente el inverso una de la otra. Para la aplicación práctica de este operador en la corrección de la distorsión de lente, véase la sección Corrección de lente. La distorsión se implementa a partir de un conjunto de 4 valores de coeficientes, conocidos como A, B, C y D, tal como los definió el profesor Helmut Dersch en un sitio web que ha desaparecido desde entonces. Puede ver una copia archivada del sitio en Wayback Machine en Correcting Barrel Distortion. Los valores forman básicamente una ecuación de distorsión tal que...

_R src_ = r * ( A*_r 3_ + B*_r 2_ + C*_r_ + D )

Donde "_r_" es el radio de destino y "_R src_" es el píxel de origen del que se obtiene el color del píxel. Los radios se normalizan de modo que el radio = '1.0' corresponde a la mitad del ancho o alto mínimo de la imagen de entrada. Esto puede parecer invertido, pero es porque se usa la técnica de mapeo inverso de píxeles para garantizar la cobertura completa de la imagen resultante. Los cuatro coeficientes (A, B, C y D) son fijos para cualquier combinación específica de cámara, lente y zoom. Estos tres datos suelen almacenarse con la imagen en un perfil EXIF. Esto es importante porque significa que, una vez que tenga estos valores para su cámara, puede usarlos para eliminar la distorsión esférica de lente presente en todas las fotos tomadas con esa combinación de cámara y lente. Los argumentos que necesita el método de distorsión '**Barrel**'. Por lo general solo se proporcionan 3 o 4 valores...

_A B C_ [ _D_ [ _X_ , _Y_ ] ]

Los argumentos opcionales X ,Y proporcionan un 'centro' opcional para la distorsión radial; de lo contrario, por defecto se usa el centro exacto de la imagen dada (independientemente de su desplazamiento virtual). Los coeficientes están diseñados de modo que, si los cuatro valores A a D suman '1.0', el ancho/alto mínimo de la imagen no cambiará. Por esta razón, si no se proporciona D (que controla el escalado global de la imagen), se establecerá de modo que los cuatro valores sumen '1.0'. Usar los parámetros '0.0 0.0 0.0' (equivalente a _A_ =_B_ =_C_ =0.0 y _D_ =1.0') no producirá ningún cambio en la imagen de entrada, y es el argumento 'no-op' para esta distorsión. Aquí hay un ejemplo del sitio web original, usando los coeficientes proporcionados para la cámara con la que se tomó la foto.

  magick barrel_distorted.jpg -virtual-pixel black \
          -distort Barrel "0.0 0.0 -0.075 1.1" \
          barrel_distorted_fixed.jpg

[IM Output] [IM Output]

Observe cómo se corrigió la distorsión de la imagen, enderezando las columnas del edificio. Sin embargo, como los 4 coeficientes sumaban un valor mayor que 1.0, la imagen se redujo ligeramente, produciendo las pequeñas áreas negras en el centro de los bordes superior e inferior (según el ajuste de píxel virtual dado). Aquí está el efecto de sumar 0.2 a cada uno de los coeficientes de entrada; de nuevo, los valores suman más de 1.0, así que la imagen distorsionada resultante será más pequeña.

  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.2 0.0 0.0 1.0"   barrel_checks_A.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.2 0.0 1.0"   barrel_checks_B.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 0.2 1.0"   barrel_checks_C.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 0.0 1.2"   barrel_checks_D.png

[IM Output] [IM Output] [IM Output] [IM Output]

Restar 0.2 produce el efecto contrario, aunque he compensado el efecto usando un valor 'D ' mayor (para reducir la imagen) de modo que pueda ver mejor los resultados.

  magick checks.png -virtual-pixel gray \
          -distort Barrel "-0.2 0.0 0.0 1.3"   barrel_checks-A.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 -0.2 0.0 1.3"   barrel_checks-B.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 -0.2 1.3"   barrel_checks-C.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 0.0 1.3"    barrel_checks-D.png

[IM Output] [IM Output] [IM Output] [IM Output]

Observe cómo el valor de A produce un efecto mayor que B , y B un efecto mayor que C , mientras que D proporciona un escalado global del resultado. Esto le permite usar cada coeficiente para ajustar la imagen de modo que pueda corregir una distorsión en torno al borde exterior y otra distorsión hacia el centro, ya sea de cojín en una y de barril en la otra. Muy versátil. Los coeficientes anteriores (A , B , C y D) están diseñados para funcionar con un radio 'normalizado' que es la mitad del ancho o alto mínimo de la imagen (como el ajuste de radio '0' de la distorsión polar. Es decir, son independientes del tamaño de la imagen. Por ello puede usar el mismo conjunto de valores para cualquier imagen que genere una cámara concreta, independientemente de su tamaño de calidad (ajuste de la cámara), o de si redimensionó la imagen a un tamaño menor. Es posible ajustar los valores de los coeficientes para usar otros valores de radio 'normalizado' aplicando los multiplicadores/divisores adecuados a cada coeficiente. Por ejemplo, usar la mitad del ancho/alto máximo, o usar el radio diagonal. | _Helmut Dersch también señala que debería considerar usar un espacio de color LAB para la corrección de distorsión en fotos, ya que produce una mejor interpolación de color. En realidad esto puede ser cierto para todas las distorsiones (incluido elredimensionado.

Las pruebas muestran que el espacio LAB es igual de no lineal que sRGB, pero sí evita la posibilidad de distorsiones de color cuando se recortan valores extremos. Véase Percepción del color humano y los ejemplos prácticos en Redimensionar con corrección de espacio de color._
---|---

También puede declarar un conjunto diferente de coeficientes para los ejes x e y, lo que le permite generar algunas distorsiones inusuales.

_A x Bx Cx Dx Ay By Cy Dy_ [ _X_ , _Y_ ]

El uso de argumentos X e Y separados se prototipó en el script pinbarrel de Fred Weinhaus, aunque sus argumentos van en orden inverso, con D primero y A al final. Usando un valor C positivo, con el valor D apropiado solo para el conjunto de coeficientes 'y', puede distorsionar las imágenes de modo que se abomben verticalmente en el centro. |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Barrel "0.0 0.0 0.0 1.0   0.0 0.0 0.5 0.5" \
          barrel_bulge.png

[IM Output]
De forma similar, usando un valor C negativo puede 'pellizcar' una imagen en el centro. |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Barrel "0.0 0.0 0.0 1.0   0.0 0.0 -0.5 1.9" \
          barrel_pinch.png

[IM Output]
O bien, añadiendo el efecto contrario para los coeficientes X, puede hacer que parezca que está apretando la imagen entre los dedos, haciendo que se abombe por los lados. |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Barrel "0.0 0.0 0.5 0.5   0.0 0.0 -0.5 1.9" \
          barrel_pinch_2.png

[IM Output]

Distorsión BarrelInverse (distorsión de barril alternativa)

El método de distorsión 'BarrelInverse' es muy similar al método de distorsión de barril anterior y, de hecho, toma el mismo conjunto de argumentos. Sin embargo, la fórmula que se aplica es ligeramente distinta: la parte principal de la ecuación divide el radio, es decir, la ecuación se ha invertido.

_R src_ = r / ( A*_r 3_ + B*_r 2_ + C*_r_ + D )

| Esta ecuación NO produce el 'inverso' de la distorsión 'Barrel'. NO puede usarla para 'deshacer' la distorsión anterior.
---|---
El resultado de esto es que usaría la forma 'negativa' de A , B , C , con un ajuste equivalente en D para lograr un resultado similar pero ligeramente distinto. Algunas fuentes, como el artículo de investigación Method for Correcting Lens Distortion (PDF), sugieren que puede lograrse un mejor resultado con una distorsión de corrección de lente de esta forma. Por ejemplo, aquí está el equivalente del último ejemplo de 'pellizco' usando esta forma de distorsión. |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort BarrelInverse "0.0 0.0 -0.5 1.5   0.0 0.0 0.3 0.5" \
          barrel_inv_pinch.png

[IM Output]


Distorsiones proyectivas

Estas son distorsiones que se usan para proyectar o mapear imágenes que existen sobre una superficie hacia otra superficie. Las líneas de proyección pueden ser paralelas o irradiar desde algún lugar concreto. Aunque técnicamente las distorsiones afines y de perspectiva también son 'proyectivas', en cuanto que 'proyectan' imágenes de una superficie plana sobre otra superficie plana (usando proyecciones paralelas y radiales, respectivamente), son tan comunes que se examinan con mayor detalle en sus propias secciones de ejemplos anteriores. Aquí están las 'distorsiones proyectivas' más inusuales que se han implementado, normalmente con la ayuda del foro de discusión de IM.

Cylinder 2 Plane

La distorsión 'Cylinder2Plane' es una distorsión proyectiva radial desde un punto en el centro de un cilindro hacia un plano que es tangente a ese cilindro.

[diagram]

Esta disposición es típica de una cámara estenopeica especial conocida como cámara P.90, donde una foto de un arco de 90 grados se capta sobre una película que forma un cilindro dentro de la cámara. Aquí hay una foto de ejemplo de una cámara así...

[photo]

El problema con esto es que la imagen resultante queda distorsionada, de modo que las líneas rectas se convierten en arcos curvos, debido a la disposición física de la película. Es esencialmente una superficie curva que se envuelve alrededor de una fuente de proyección 'puntual' (un orificio estenopeico). Tenga en cuenta que una cámara estenopeica normal no tiene este problema, ya que se proyecta sobre una superficie plana desde una fuente puntual. La distorsión 'Cylinder2Plane' corrige esto proyectando la imagen desde su disposición cilíndrica sobre un plano. Toma los parámetros...

_fov_angle center_x,y fov_output dest_center_x,y_

Solo se requiere el primer parámetro, el ángulo del campo de visión de la cámara. Una cámara P.90 usaba una distancia focal (radial) de 90 mm y una película estándar de 57 mm de ancho, lo que a su vez produce un 'campo de visión' de 90 / 57 * 180/pi, es decir, 90.467 grados. Aquí, por ejemplo, proyecto una foto P90 sobre un plano para que la imagen parezca más 'normal' y para enderezar de nuevo las líneas rectas.

  magick p90_orig.jpg -virtual-pixel Gray \
          +distort Cylinder2Plane 90.467  p90_plane.png

[IM Output]

Observe que tanto el ancho como el alto de la imagen han cambiado, ya que usamos la versión 'plus' de la distorsión, con el fin de mostrar todos los píxeles distorsionados de la imagen original. Es más ancha por causa de la proyección, mientras que el alto de la imagen real a lo largo de la línea central vertical no cambió. La foto y el algoritmo provienen de una discusión de IM, Correcting for a curved film plane. La discusión también derivó en otra sobre Algorithmic vignetting correction for pinhole cameras.
El parámetro especial 'fov_output ', si se proporciona, escalará la imagen de salida resultante de modo que el ancho de la imagen de salida (normalmente el tamaño de una ventana de visualización) coincida exactamente con este ángulo. Si no se proporciona ninguna ventana de visualización, se activa un mejor ajuste para aproximar lo mejor posible un escalado 1:1 de la imagen, manteniendo a la vez los bordes de la imagen alineados con números enteros. El parámetro del punto central de la distorsión (el punto de tangencia y de horizonte de la entrada). El último parámetro 'center' controla el posicionamiento preciso en coma flotante de los resultados dentro de la 'capa' de imagen de la ventana de visualización (es decir, traslaciones de subpíxeles). Esto, junto con el parámetro 'center_x,y ', le permite extraer partes de una imagen más grande. Por ejemplo, extraer una pequeña vista de 90 grados de una imagen panorámica de 360 grados más grande. FUTURO: extraer imágenes planas de 'visualización' más pequeñas de un panorama de 360, así como una animación que recorra lentamente esos 360 grados.

Plane 2 Cylinder

La distorsión 'Plane2Cylinder' es el inverso de la proyección anterior y toma los parámetros...

_fov_angle center_x,y_

Por ejemplo, esto deshace el ejemplo anterior de la cámara P.90.

  magick p90_plane.png -virtual-pixel Black \
          +distort Plane2Cylinder 90.467  p90_restored.png

[IM Output]

Los resultados aún contienen los píxeles adicionales que se añadieron previamente, y agregan aún más. Estos deberían recortarse del resultado anterior. Aquí uso esta distorsión para generar una animación de una 'tira de película' completa con los orificios dentados del borde de la película.

  magick -size 12x12 xc: -draw 'circle 6,6 6,2' -negate \
          -duplicate 5 +append +duplicate \
          rose: +swap -background black -append \
          -duplicate 3 +append \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -duplicate 19  -distort SRT '%[fx:72*t/n],0 1 0 0,0' \
          -distort Plane2cylinder 115 \
          -bordercolor Skyblue -border 0x3 -set delay 5 \
          film_strip_anim.gif

[IM Output]

Explicación:

  • Primero se dibuja una imagen de orificio, que se duplica y concatena para formar una secuencia de 6 orificios. Luego se duplica de nuevo.
  • A continuación se añade una imagen de rosa integrada y se intercala entre las dos copias de estos orificios dentados, concatenándolas (con relleno negro) para crear un solo fotograma de la tira de película final.
  • Esto se duplica para crear una tira de película de 4 fotogramas, que definirá la longitud de la imagen final.
  • Se crea una animación de 20 fotogramas usando distorsiones SRT de 'traslación'. Véase Animaciones con distorsión.
  • Luego cada uno de esos 20 fotogramas se distorsiona sobre un cilindro a lo largo de un arco de 115 grados, usando un ajuste de píxel virtual para generar una baldosa horizontal infinita de la tira de película.
  • El ángulo en este caso es solo para el ancho de la imagen de entrada; el ancho de la imagen final es de más de 180 grados, ya que no usé una versión 'plus' de la distorsión. Así que, aunque el ancho distorsionado se reduce a lo ancho, la imagen de salida no lo hace.
  • Se añade un borde final y se aplican los ajustes de animación.

Distorsiones multipunto y de forma libre

Distorsión de Shepard (distorsión tipo caramelo)

El método de Shepard (añadido en IM v6.4.2-4) usa el movimiento de los puntos de control dados para distorsionar la imagen en términos de efectos 'locales'. Puede imaginarlo como el equivalente a un bloque grueso de 'caramelo masticable' que representa la imagen de origen, en el que se clavan alfileres que luego se mueven de un lado a otro. Más técnicamente, mueve puntos según una interpolación por distancia inversa al cuadrado. Si solo se usa un punto de control, naturalmente toda la imagen se mueve (se traslada), igual que ocurriría con una distorsión '[Affine](#affine)' de un punto. No muy interesante. Así que probemos a mover dos puntos de control. Por ejemplo, torturemos al 'koala' tirándole de las orejas (en '30,11' y '48,29')...

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull.png

[IM Output] [IM Output]

Como puede ver, las partes de la imagen situadas entre los dos puntos de control se estiraron por el movimiento de estos. Sin embargo, todas las demás partes de la imagen quedaron prácticamente intactas, incluida la zona cercana al propio punto de control, la parte inferior de la imagen, etc. El área que queda en medio, entre los puntos de control, se tiró y estiró para garantizar que los puntos de control quedaran situados donde usted lo pidió. Lo que quizá no sea tan evidente es que las partes del lado opuesto de los puntos de control también se comprimen, de modo que, a medida que se aleja, los puntos de control tienen menos influencia sobre el resultado. Es decir, esta distorsión genera una distorsión 'localizada'. Ampliemos nuestra vista (usando una ventana de visualización de distorsión) para verlo mejor... |

  magick koala.gif -virtual-pixel Black \
          -set option:distort:viewport 115x115-20-20 \
          -distort Shepards '30,11 15,11  48,29 58,29' \
          +repage koala_ear_pull_2.png

[IM Output]
Como puede ver, la forma de la imagen también se distorsionó para acomodar la 'cabeza' estirada del koala. Para evitar este efecto, lo más habitual es 'clavar' también las esquinas y posiblemente algunos de los bordes de la imagen, de modo que no se muevan. |

  magick koala.gif -virtual-pixel Black \
          -set option:distort:viewport 115x115-20-20 \
          -distort Shepards '30,11 15,11  48,29 58,29
              0,0 0,0  0,74 0,74   74,0 74,0  74,74 74,74' \
          +repage koala_ear_pull_3.png

[IM Output]
Incluso mover un solo punto, mientras se clavan otros puntos (solo las esquinas en este caso), puede resultar útil. Por ejemplo, movamos simplemente la nariz del koala (en '28,24') hacia el centro de la imagen. |

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '28,24 37,37
              0,0 0,0  0,74 0,74   74,0 74,0  74,74 74,74' \
          +repage koala_move_nose.png

[IM Output]
Este ejemplo concreto es especial, ya que es la distorsión que usa Fred Weinhaus en su script de 'morphing animado' de un solo punto "[shapemorph](http://www.fmwconcepts.com/imagemagick/shapemorph/)". Sin embargo, su script original usaba un lento operador FX casero, ya que la distorsión de Shepard aún no se había añadido a IM. De hecho, este script fue el origen de la idea de la distorsión de Shepard.

Mover áreas de una imagen

Incluso puede mover secciones enteras de la imagen moviendo a la vez un conjunto de puntos alrededor de esa sección. Por ejemplo, movamos la cabeza del koala lateralmente usando puntos alrededor de la cabeza (línea roja), pero clavando también las partes de la imagen que no queremos mover (línea verde).

  magick koala.gif -virtual-pixel Black -distort Shepards \
            '19,8, 29,8   19,27 29,27   26,34 36,34
                 33,37 43,37   36,37 46,37   53,37 63,37   58,25 68,25
             13,20 13,20  17,28 17,28  25,36 25,36
                 35,39 35,39   46,40 46,40   50,43 50,43 ' \
          +repage koala_head_move.png

[IM Output] [IM Output]

Observe que, si bien la cabeza se movió, el borde de la cabeza queda muy distorsionado. La razón es que la distorsión no mueve áreas, sino puntos. Si esos puntos que marcan el borde están demasiado separados, la imagen tenderá a chorrear, fugarse o doblarse entre esos puntos, igual que el caramelo o la gelatina. (NOTA: el término real es estirar una 'lámina de goma' o 'globo'). Además, si dos puntos de control están cerca entre sí pero se mueven en direcciones o cantidades distintas, la imagen podría arremolinarse y doblarse localmente alrededor de ellos. Los puntos de control acaban en las ubicaciones correctas, pero todo lo demás a su alrededor se deforma severamente para lograr ese objetivo. Y eso es lo que está ocurriendo a lo largo del borde de la cabeza. Entonces, ¿qué tan cerca deberían estar los puntos que marcan el borde? Básicamente, al menos a la mitad de la distancia respecto a cualquier otro punto que se mueva de forma distinta. Así que, o bien añada más puntos de borde, o bien deje algo más de distancia entre los puntos fijos y los puntos que se mueven. Al hacerlo, definirá mejor el espacio en el que la imagen puede estirarse y comprimirse. Observe también que, en general, toda la imagen también se movió hacia la izquierda, junto con la cabeza. Solo los puntos de control que se fijaron o se movieron a destinos concretos tienen garantizada una colocación correcta. Cualquier parte de la imagen más alejada de los puntos de control también se moverá según un promedio aproximado de todos los movimientos de los puntos de control. Por tanto, es mejor tener muchos más puntos 'fijos', repartidos por toda la imagen, o incluso algunos puntos movidos negativamente a cierta distancia fuera de la imagen, para compensar el movimiento promedio general. También puede duplicar o repetir puntos de control (listándolos dos veces) para dar a puntos concretos más influencia o 'fuerza' sobre la distorsión en esa zona. Aquí hay otra versión de 'mover la cabeza lateralmente', pero esta vez di algo más de separación entre los puntos que se mueven (rojos) y los fijos (verdes). También añadí muchos más puntos fijos para reducir el movimiento general promedio de la imagen distorsionada.

  magick koala.gif -virtual-pixel Black -distort Shepards \
            '15,15, 25,15   19,27 29,27   26,34 36,34
                33,37 43,37   36,37 46,37    53,37 63,37
             10,2 10,2   2,10 2,10   4,55 4,55   14,47 14,47
                25,47 25,47 45,51 45,51   55,45 55,45
                5,70 5,70  15,60 15,60   55,60 55,60   70,70 70,70' \
          +repage koala_head_move_2.png

[IM Output] [IM Output]

Lo último que queda por hacer en lo anterior es simplemente fijar un mejor ajuste "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" para definir de qué color deberían ser las áreas negras indefinidas de arriba.

Shepard y las rotaciones de imagen

Un aspecto de esta distorsión es que ¡no le gusta ninguna forma de rotación! Por ejemplo, aquí hay una repetición de las distorsiones de perspectiva y BilinearForward, junto a la distorsión de Shepard.

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort Perspective \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_pers.jpg

  magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
       -distort BilinearForward \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_blin.jpg
  magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
       -distort Shepards \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_shep.jpg

[IM Output]
Original | | [IM Output]
Perspectiva | [IM Output]
Bilineal | [IM Output]
Shepard
---|---|---|---|---

Observe cómo la distorsión de Shepard produjo una imagen muy curva en comparación con los otros dos métodos de distorsión. Eso se debe a que intenta preservar la imagen exactamente en el área cercana a los puntos de control dados. Y eso incluye la rotación de la imagen. Como resultado de esta 'preservación', la cuadrícula se curva de modo que se mantiene 'ortogonal' en el punto de control real. Es un poco como si esos 'alfileres' en los puntos de control no fueran en realidad alfileres redondos, sino 'cruces', que obligan a la 'gelatina' o 'lámina de goma' que sostiene la imagen a preservar también la rotación de la imagen. Esto es también el origen de muchos de los efectos de 'remolino' que puede producir esta distorsión. Por ejemplo, si tomamos dos puntos de la imagen y los empujamos uno más allá del otro, la imagen se arremolinará, no rotará. Por ejemplo, intentemos empujar las orejas del koala una hacia la otra en lugar de separarlas.

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '30,11 40,11  48,29 38,29' \
          koala_ear_push.png

[IM Output] [IM Output]

Factor de potencia de Shepard

Normalmente, los pesos de distancia de un IWD (distancia inversa ponderada) de Shepard siguen una ley del inverso del cuadrado (1/r2); sin embargo, a partir de IM v6.8.0-10 ya puede usar el define experto 'shepards:power' para controlar el 'nivel de potencia' de los pesos globales. Si no se define, tiene un valor de 2.0, pero al definirlo más pequeño puede generar distorsiones más localizadas alrededor de los puntos de control movidos respecto al desplazamiento promedio global de la imagen distorsionada. Usar un valor mayor generará un área de efecto más grande alrededor de los puntos de control. Por ejemplo, aquí hay una repetición del ejemplo de 'tirar de las orejas del koala', con distintos niveles de potencia aplicados a los pesos de la distorsión.

  magick koala.gif -virtual-pixel Black -define shepards:power=0.5 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow0.5.png
  magick koala.gif -virtual-pixel Black -define shepards:power=1.0 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow1.png

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull.png
  magick koala.gif -virtual-pixel Black -define shepards:power=3.0 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow3.png
  magick koala.gif -virtual-pixel Black -define shepards:power=8.0 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow8.png

[IM Output]
Original
y acción | | [IM Output]
potencia 0.5 | [IM Output]
potencia 1.0 | [IM Output]
potencia 2.0
(por defecto) | [IM Output]
potencia 3.0 | [IM Output]
potencia 8.0
---|---|---|---|---|---|---

Todos los resultados de imagen anteriores usan exactamente el mismo conjunto de movimientos de puntos de control. La única diferencia es el área de efecto alrededor de esos puntos de control. Una potencia pequeña 'localizará' los movimientos solo en el área cercana al punto de control, mientras que potencias mayores arrastrarán más de la imagen junto con el punto de control. Con potencias muy grandes, esta atracción tenderá a 'desgarrar' la imagen en áreas separadas a lo largo de las líneas equidistantes entre los puntos de control. Incluso podría usar potencias mucho mayores, que simplemente trasladarán regiones alrededor del punto de control de origen a áreas alrededor del punto de control de destino. Estas áreas formarán un patrón de 'regiones de Voronoi' y pueden contener copias duplicadas de la imagen de origen. Por ejemplo, aquí mapeo el área alrededor de la nariz del koala (en las coordenadas 28,24) a 7 áreas diferentes en un patrón hexagonal, produciendo un efecto tipo 'ojo de insecto' de manera muy eficiente. |

  magick koala.gif -virtual-pixel Black -define shepards:power=25 \
          -distort Shepards '28,24 35,35 \
                      28,24 20,10   28,24 50,10 \
                      28,24 20,60   28,24 50,60 \
                      28,24 10,35   28,24 60,35'  koala_hexagonal.png

[IM Output]
Recuerde que la distorsión de Shepard es en realidad equivalente a un mapa de desplazamiento (que mapea los píxeles de destino a la imagen de origen) generado con la misma técnica que el operador de color disperso de Shepard, que también se ve afectado por este mismo define del factor de potencia.

La distorsión de Shepard, en resumen

La distorsión de Shepard es un método muy versátil y de forma libre, que limita sus distorsiones a las áreas marcadas por los movimientos, o no movimientos, de los puntos dados. Sus distorsiones son localizadas y están restringidas según las distancias entre los puntos de control vecinos, aunque todos los puntos siguen teniendo un efecto global promediado. Recuerde simplemente que esta distorsión se rige por puntos, no por líneas ni áreas, de modo que las partes situadas entre los puntos pueden abombarse o arremolinarse de forma inesperada cuando puntos de control que se mueven de forma distinta se sitúan demasiado cerca entre sí. Arremolinará, estirará y comprimirá la imagen entre los puntos de control, pero se esfuerza por no rotar ni escalar la imagen cerca de los puntos de control. Y, por último, puede producir una traslación promedio general de la imagen lejos de cualquier punto de control. Sin embargo, si bloques de puntos de control pueden moverse preservando sus posiciones relativas generales, sí proporciona una forma de implementar una técnica de 'morphing de imagen' general y muy sencilla regida por puntos. El script 'shapemorph2' de Fred Weinhaus usa la distorsión de Shepard para proporcionar un buen programa de propósito general de 'morphing animado de imágenes'. Internamente, esta distorsión equivale a usar el generador de degradado decolor disperso de Shepard para crear dos mapas de desplazamiento relativos con los que distorsionar la imagen. Esto es lo que hace el script original "[shapemorph](http://www.fmwconcepts.com/imagemagick/shapemorph/)" de Fred Weinhaus, y fue el origen de la técnica de distorsión.
Debido a la complejidad de los cálculos necesarios al usar ladistorsión de Shepard, IM no proporciona ninguna forma de ventana de visualización de destino de 'mejor ajuste' usando la forma plus "[+distort](#distort_bestfit)" del operador. No obstante, todavía puede usar la opción ventana de visualización de distorsión para definir una imagen de salida más grande.
--- ---
Por las mismas razones, elremuestreo de área está desactivado. Por ello, las áreas de compresión extrema (más de un factor de 2) probablemente mostrarán algunos efectos de aliasing. Por ejemplo, vea los bordes del patrón hexagonal en el último ejemplo. Sin embargo, puede usarse el supermuestreo para mejorar la calidad final de la imagen de los resultados y reducir dichos efectos de aliasing.
--- ---