Interpolación bilineal de imágenes / escalado – Un ejemplo de cálculo

Me gustaría señalar este gráfico muy perspicaz de Wikipedia que ilustra cómo hacer la interpolación bilineal para un punto:

Fuente: Wikipedia

Como puedes ver, los cuatro puntos rojos son los que se conocen. Estos puntos se conocen de antemano y P es el punto que queremos interpolar. Como tal, tenemos que hacer dos pasos (como has indicado en tu post). Para manejar la coordenada x (horizontal), debemos calcular cuál es el valor interpolado por filas para la fila superior de puntos rojos y la fila inferior de puntos rojos. El resultado son los dos puntos azules R1 y R2. Para manejar la coordenada y (vertical), usamos los dos puntos azules e interpolamos verticalmente para obtener el punto final P.

Cuando se redimensiona una imagen, aunque no veamos visualmente lo que voy a decir, pero imaginemos que esta imagen es una señal 3D f. Cada punto de la matriz es de hecho una coordenada 3D donde la ubicación de la columna es el valor x, la ubicación de la fila es el valor y y el valor z es la cantidad / valor de escala de grises de la propia matriz. Por lo tanto, hacer z = f(x,y) es el valor de la matriz en la ubicación (x,y) en la matriz. En nuestro caso, porque se trata de imágenes, cada valor de (x,y) son enteros que van desde 1 hasta tantas filas/columnas como tengamos dependiendo de la dimensión que estemos mirando.

Por lo tanto, dada la coordenada que se quiere interpolar en (x,y), y dadas las coordenadas rojas en la imagen de arriba, que las llamamos x1,y1,x2,y2 según el diagrama – específicamente yendo con la convención del diagrama y haciendo referencia a cómo se accede a las imágenes: x1 = 1, x2 = 2, y1 = 2, y2 = 1, las coordenadas azules R1 y R2 se calculan a través de la interpolación 1D columna sabia usando la misma fila ambos puntos coinciden en:

R1 = f(x1,y1) + (x - x1)/(x2 - x1)*(f(x2,y1) - f(x1,y1))R2 = f(x1,y2) + (x - x1)/(x2 - x1)*(f(x2,y2) - f(x1,y2))

Es importante tener en cuenta que (x - x1) / (x2 - x1) es un peso / proporción de la cantidad de una mezcla de la salida consiste en entre los dos valores vistos en f(x1,y1) y f(x2,y1) para R1 o f(x1,y2) y f(x2,y2) para R2. En concreto, x1 es el punto de partida y (x2 - x1) es la diferencia de valores de x. Se puede comprobar que sustituyendo x1 como x nos da 0 mientras que x2 como x nos da 1. Este peso fluctúa entre , lo cual es necesario para que los cálculos funcionen.

Hay que tener en cuenta que el origen de la imagen está en la esquina superior izquierda, por lo que (1,1) está en la esquina superior izquierda. Una vez que encuentre R1 y R2, podemos encontrar P interpolando fila a fila:

P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)

De nuevo, (y - y2) / (y2 - y1) denotan la proporción / mezcla de cuánto R1 y R2 contribuyen a la salida final P. Como tal, has calculado f5 correctamente porque has utilizado cuatro puntos conocidos: El superior izquierdo es 100, el superior derecho es 50, el inferior izquierdo es 70 y el inferior derecho es 20. En concreto, si quieres calcular f5, esto significa que (x,y) = (1.5,1.5) porque estamos a mitad de camino entre el 100 y el 50 debido a que estás escalando la imagen por dos. Si introduces estos valores en el cálculo anterior, obtendrás el valor de 60 como esperabas. Los pesos de ambos cálculos también darán como resultado 0.5, que es lo que obtuviste en tus cálculos y es lo que esperamos.

Si calculas f1, esto corresponde a (x,y) = (1.5,1) y si lo sustituyes en la ecuación anterior, verás que (y - y2)/(y2 - y1) te da 0 o el peso es 0, y así lo que se computa es sólo R2, correspondiente a la interpolación lineal a lo largo de la fila superior solamente. Del mismo modo, si calculamos f7, esto significa que queremos interpolar en (x,y) = (1.5,2). En este caso, verás que (y - y2) / (y2 - y1) es 1 o el peso es 1 y por lo tanto P = R2 + (R1 - R2), que se simplifica a R1 y es la interpolación lineal a lo largo de la fila inferior solamente.

Ahora está el caso de f3 y f5. Ambos corresponden a (x,y) = (1,1.5) y (x,y) = (2,1.5) respectivamente. Sustituyendo estos valores por R1 y R2 y P para ambos casos se obtiene:

f3

R1 = f(1,2) + (1 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(1,2)R2 = f(1,1) + (1 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,1)P = R1 + (1.5 - 1)*(R1 - R2) = f(1,2) + 0.5*(f(1,2) - f(1,1))P = 70 + 0.5*(100 - 70) = 85

f5

R1 = f(1,2) + (2 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(2,2)R2 = f(1,1) + (2 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,2)P = R1 + (1.5 - 1)*(R1 - R2) = f(2,2) + 0.5*(f(2,2) - f(1,2))P = 20 + 0.5*(50 - 20) = 35

¿Qué nos dice esto? Significa que se está interpolando sólo en la dirección y. Esto es evidente cuando echamos un vistazo a P. Al examinar los cálculos más a fondo de P para cada uno de f3 y f5, se ve que estamos considerando los valores a lo largo de la dirección vertical solamente.

Como tal, si quieres una respuesta definitiva, f1 y f7 se encuentran interpolando a lo largo de la dirección x / columna sólo a lo largo de la misma fila. f3 y f5 se encuentran interpolando y / dirección de la fila a lo largo de la misma columna. f4 utiliza una mezcla de f1 y f7 para calcular el valor final como ya has visto.

Para responder a tu última pregunta, f2, f6 y f8 se rellenan en base a la preferencia personal. Estos valores se consideran fuera de los límites, con los valores x y y ambos son 2.5 y eso está fuera de nuestra cuadrícula para (x,y). En MATLAB, la implementación por defecto de esto es llenar cualquier valor fuera de los límites definidos para ser no-un-número (NaN), pero a veces, la gente extrapola utilizando la interpolación lineal, copiar los valores de los bordes, o realizar algún relleno elaborado como el relleno simétrico o circular. Depende de la situación en la que te encuentres, pero no hay una respuesta correcta y definitiva sobre cómo rellenar f2, f6 y f8 – todo depende de tu aplicación y de lo que tenga más sentido para ti.

Como extra, podemos verificar que mis cálculos son correctos en MATLAB. Primero definimos una cuadrícula de (x,y) puntos en el rango , luego redimensionamos la imagen para que sea el doble de grande donde especificamos una resolución de 0,5 por punto en lugar de 1. Voy a llamar a su matriz definida A:

A = ; %// Define original matrix = meshgrid(1:2,1:2); %// Define original grid of points = meshgrid(1:0.5:2.5,1:0.5:2.5) %// Define expanded grid of pointsB = interp2(X,Y,A,X2,Y2,'linear'); %// Perform bilinear interpolation

La rejilla original de (x,y) puntos tiene el siguiente aspecto:

>> XX = 1 2 1 2>> YY = 1 1 2 2

La rejilla expandida para ampliar el tamaño de la matriz al doble tiene el siguiente aspecto:

>> X2X2 = 1.0000 1.5000 2.0000 2.5000 1.0000 1.5000 2.0000 2.5000 1.0000 1.5000 2.0000 2.5000 1.0000 1.5000 2.0000 2.5000>> Y2Y2 = 1.0000 1.0000 1.0000 1.0000 1.5000 1.5000 1.5000 1.5000 2.0000 2.0000 2.0000 2.0000 2.5000 2.5000 2.5000 2.5000

B es la salida utilizando X y Y como la rejilla original de puntos y X2 y Y2 son los puntos que queremos interpolar.

Obtenemos:

>> BB = 100 75 50 NaN 85 60 35 NaN 70 45 20 NaN NaN NaN NaN NaN

Deja un comentario