Main Content

Relleno y cizallamiento de una imagen simultáneamente

En este ejemplo se muestra cómo construir una estructura que representa una transformación de cizallamiento simple y, a continuación, se aplica a una imagen.tform Exploramos cómo la transformación afecta a líneas rectas y círculos, y luego la usamos como un vehículo para explorar las diversas opciones de relleno de imágenes que se pueden utilizar con y .imtransformtformarray

Paso 1: Transformar una imagen usando simple cizallamiento

En dos dimensiones, una transformación de corte simple que asigna un par de coordenadas de entrada a un par de coordenadas de salida tiene el formulario[u v][x y]

<math display="block">
<mrow>
<mi>x</mi>
<mo>=</mo>
<mi>u</mi>
<mo>+</mo>
<mi>a</mi>
<mo>*</mo>
<mi>v</mi>
</mrow>
</math>

<math display="block">
<mrow>
<mi>y</mi>
<mo>=</mo>
<mi>v</mi>
</mrow>
</math>

donde hay una constante.a

Cualquier cizallamiento simple es un caso especial de una transformación afín. Usted puede verificar fácilmente que

<math display="block">
<mrow>
<mo stretchy="false">[</mo>
<mtable columnalign="center center">
<mtr>
<mtd>
<mrow>
<mi>x</mi>
<mspace width="0.5em"></mspace>
<mi>y</mi>
<mspace width="0.5em"></mspace>
<mn>1</mn>
</mrow>
</mtd>
</mtr>
</mtable>
<mo stretchy="false">]</mo>
<mo>=</mo>
<mo stretchy="false">[</mo>
<mtable columnalign="center center">
<mtr>
<mtd>
<mrow>
<mi>u</mi>
<mspace width="0.5em"></mspace>
<mi>v</mi>
<mspace width="0.5em"></mspace>
<mn>1</mn>
</mrow>
</mtd>
</mtr>
</mtable>
<mo stretchy="false">]</mo>
<mo>*</mo>
<mrow>
<mo>[</mo>
<mtable columnalign="center center center">
<mtr>
<mtd>
<mrow>
<mn>1</mn>
<mspace width="0.2777777777777778em"></mspace>
<mn>0</mn>
<mspace width="0.2777777777777778em"></mspace>
<mn>0</mn>
</mrow>
</mtd>
</mtr>
<mtr>
<mtd>
<mrow>
<mi>a</mi>
<mspace width="0.2777777777777778em"></mspace>
<mn>1</mn>
<mspace width="0.2777777777777778em"></mspace>
<mn>0</mn>
</mrow>
</mtd>
</mtr>
<mtr>
<mtd>
<mrow>
<mn>0</mn>
<mspace width="0.2777777777777778em"></mspace>
<mn>0</mn>
<mspace width="0.2777777777777778em"></mspace>
<mn>1</mn>
</mrow>
</mtd>
</mtr>
</mtable>
<mo>]</mo>
</mrow>
</mrow>
</math>

produce los valores para y que recibió de las dos primeras ecuaciones.xy

Ajuste de 0.45, construimos una estructura afín usando .atformmaketform

a = 0.45; T = maketform('affine', [1 0 0; a 1 0; 0 0 1] );

Seleccionamos, leemos, vemos y visualizamos e imagen para transformar.

A = imread('football.jpg'); h1 = figure; imshow(A); title('Original Image');

Elegimos un tono de naranja como nuestro valor de relleno.

orange = [255 127 0]';

Estamos listos para usar para transformar .TUn Podríamos llamar de la siguiente manera:imtransform

B = imtransform(A,T,'cubic','FillValues',orange);

pero esto es un desperdicio ya que aplicaríamos interpolación cúbica a lo largo de columnas y filas. (Con nuestra transformación de cizallamiento puro, realmente sólo necesitamos interpolar a lo largo de cada fila.) En su lugar, creamos y usamos un remuestreador que aplica interpolación cúbica a lo largo de las filas, pero simplemente utiliza la interpolación de vecino más cercana a lo largo de las columnas, luego llamamos y mostramos el resultado.imtransform

R = makeresampler({'cubic','nearest'},'fill'); B = imtransform(A,T,R,'FillValues',orange);  h2 = figure; imshow(B); title('Sheared Image');

Paso 2: Explora la transformación

Transformar una cuadrícula de líneas rectas o una matriz de círculos con es una buena manera de entender una transformación (siempre y cuando tenga funciones hacia adelante e inversas).tformfwd

Defina una cuadrícula de líneas que cubra la imagen original y muéstrenla sobre la imagen A continuación, utilice aplicar el cizallamiento puro a cada línea de la cuadrícula y mostrar el resultado sobre la imagen cizallada.tformfwd

[U,V] = meshgrid(0:64:320,0:64:256); [X,Y] = tformfwd(T,U,V); gray = 0.65 * [1 1 1];  figure(h1); hold on; line(U, V, 'Color',gray); line(U',V','Color',gray);

 figure(h2); hold on; line(X, Y, 'Color',gray); line(X',Y','Color',gray);

Puede hacer lo mismo con una matriz de círculos.

gray = 0.65 * [1 1 1]; for u = 0:64:320     for v = 0:64:256         theta = (0 : 32)' * (2 * pi / 32);         uc = u + 20*cos(theta);         vc = v + 20*sin(theta);         [xc,yc] = tformfwd(T,uc,vc);         figure(h1); line(uc,vc,'Color',gray);         figure(h2); line(xc,yc,'Color',gray);     end end

Paso 3: Compare los métodos de Pad 'relleno', 'replicar' y 'enlazado'

Cuando aplicamos la transformación de cizallamiento, rellenamos los triángulos naranjas a la izquierda y a la derecha, donde no había datos.imtransform Esto se debe a que especificamos un método pad de al llamar a .'fill'makeresampler Hay un total de cinco opciones de método de pad diferentes ( , , , , y ).'fill''replicate''bound''circular''symmetric' Aquí comparamos los tres primeros.

En primer lugar, para ver mejor cómo funcionaba la opción, utilice las opciones y para forzar un poco de espacio adicional alrededor de la imagen de salida.'fill''XData''YData'imtransform

R = makeresampler({'cubic','nearest'},'fill');  Bf = imtransform(A,T,R,'XData',[-49 500],'YData',[-49 400],...                  'FillValues',orange);  figure, imshow(Bf); title('Pad Method = ''fill''');

Ahora, pruebe el método (no es necesario especificar valores de relleno en este caso).'replicate'

R = makeresampler({'cubic','nearest'},'replicate'); Br = imtransform(A,T,R,'XData',[-49 500],'YData', [-49 400]);  figure, imshow(Br); title('Pad Method = ''replicate''');

Y prueba el método.'bound'

R = makeresampler({'cubic','nearest'}, 'bound'); Bb = imtransform(A,T,R,'XData',[-49 500],'YData',[-49 400],...                  'FillValues',orange); figure, imshow(Bb); title('Pad Method = ''bound''');

Resultados con y se ven muy similares, pero mira de cerca y verás que los bordes son más suaves con .'fill''bound''fill' Esto se debe a que la imagen de entrada se rellena con los valores de relleno, a continuación, la interpolación cúbica se aplica a través del borde, mezclando los valores de relleno e imagen. Por el contrario, reconoce un límite estricto entre el interior y el exterior de la imagen de entrada.'bound' Los puntos que caen fuera se llenan. Los puntos que caen dentro se interpolan mediante la replicación cuando están cerca del borde. Una mirada de cerca ayuda a mostrar esto más claramente. Elegimos y rodamos un punto cerca de la esquina inferior derecha de la imagen, en el espacio de la imagen de salida, el cambio de tamaño para conservar la apariencia de los píxeles individuales.XDataYData'nearest'

R = makeresampler({'cubic','nearest'},'fill'); Cf = imtransform(A,T,R,'XData',[423 439],'YData',[245 260],...                  'FillValues',orange);  R = makeresampler({'cubic','nearest'},'bound'); Cb = imtransform(A,T,R,'XData',[423 439],'YData',[245 260],...                  'FillValues',orange);  Cf = imresize(Cf,12,'nearest'); Cb = imresize(Cb,12,'nearest');  figure; subplot(1,2,1); imshow(Cf); title('Pad Method = ''fill'''); subplot(1,2,2); imshow(Cb); title('Pad Method = ''bound''');

Paso 4: Ejercita los métodos de Pad 'circular' y 'simétrico'

Los dos métodos de pad restantes son (repetición circular en cada dimensión) y (repetición circular de la imagen con una imagen reflejada anexa).'circular''symmetric' Para mostrar más del patrón que emerge, redefinimos la transformación para cortar la escala a la mitad.

Thalf = maketform('affine',[1 0; a 1; 0 0]/2);  R = makeresampler({'cubic','nearest'},'circular'); Bc = imtransform(A,Thalf,R,'XData',[-49 500],'YData',[-49 400],...                  'FillValues',orange); figure, imshow(Bc); title('Pad Method = ''circular''');

R = makeresampler({'cubic','nearest'},'symmetric'); Bs = imtransform(A,Thalf,R,'XData',[-49 500],'YData',[-49 400],...                  'FillValues',orange); figure, imshow(Bs); title('Pad Method = ''symmetric''');