Gostaria de apontar para este gráfico muito perspicaz da Wikipedia que ilustra como fazer interpolação bilinear para um ponto:
Source: Wikipédia
Como pode ver, os quatro pontos vermelhos são o que é conhecido. Estes pontos que você conhece antes da mão e P
é o ponto que nós desejamos interpolar. Como tal, temos que fazer dois passos (como você indicou no seu post). Para lidar com a coordenada x
(horizontal), devemos calcular qual o valor interpolado para a linha superior dos pontos vermelhos e a linha inferior dos pontos vermelhos. Isto resulta nos dois pontos azuis R1
e R2
. Para lidar com a coordenada y
(vertical), usamos os dois pontos azuis e interpolamos verticalmente para obter o ponto final P
ponto.
Quando se redimensiona uma imagem, apesar de não vermos visualmente o que vou dizer, mas imagine que esta imagem é um sinal 3D f
. Cada ponto da matriz é de facto uma coordenada 3D onde a localização da coluna é o valor x
, a localização da linha é o valor y
e o valor z
é a quantidade / escala de cinzentos da própria matriz. Portanto, fazendo z = f(x,y)
é o valor da matriz na localização (x,y)
na matriz. No nosso caso, porque você está lidando com imagens, cada valor de (x,y)
são inteiros que vão de 1 a tantas linhas/colunas quantas tivermos, dependendo da dimensão que você estiver olhando.
Portanto, dada a coordenada que você quer interpolar em (x,y)
, e dadas as coordenadas vermelhas na imagem acima, que chamamos de x1,y1,x2,y2
conforme o diagrama – especificamente indo com a convenção do diagrama e referenciando como as imagens são acessadas: x1 = 1, x2 = 2, y1 = 2, y2 = 1
, as coordenadas azuis R1
e R2
são calculadas através da coluna de interpolação 1D usando a mesma linha ambos os pontos coincidem em:
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))
É importante notar que (x - x1) / (x2 - x1)
é um peso / proporção de quanto de uma mistura a saída consiste entre os dois valores vistos em f(x1,y1)
e f(x2,y1)
para R1
ou f(x1,y2)
e f(x2,y2)
para R2
. Especificamente, x1
é o ponto de partida e (x2 - x1)
é a diferença em x
valores. Você pode verificar que a substituição de x1
por x
nos dá 0 enquanto x2
por x
nos dá 1. Este peso varia entre que é necessário para que os cálculos funcionem.
É de notar que a origem da imagem está no canto superior esquerdo, e assim (1,1)
está no canto superior esquerdo. Assim que encontrar R1
e R2
, podemos encontrar P
interpolando a linha wise:
P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)
Again, (y - y2) / (y2 - y1)
denotar a proporção / mistura de quanto R1
e R2
contribuir para a saída final P
. Como tal, você calculou f5
corretamente porque você usou quatro pontos conhecidos: O superior esquerdo é 100, o superior direito é 50, o inferior esquerdo é 70 e o inferior direito é 20. Especificamente, se você quiser calcular f5
, isto significa que (x,y) = (1.5,1.5)
porque estamos a meio caminho entre os 100 e 50 devido ao facto de que você está a escalar a imagem por dois. Se ligar estes valores ao cálculo acima, obterá o valor de 60, como esperava. Os pesos para ambos os cálculos também resultarão em 0.5
, que é o que você tem nos seus cálculos e é o que esperamos.
Se você calcular f1
, isto corresponde a (x,y) = (1.5,1)
e se você substituir isto na equação acima, você verá que (y - y2)/(y2 - y1)
lhe dá 0 ou o peso é 0, e assim o que é calculado é apenas R2
, correspondendo à interpolação linear ao longo da linha superior apenas. Da mesma forma, se calcularmos f7
, isto significa que queremos interpolar a (x,y) = (1.5,2)
. Neste caso, você verá que (y - y2) / (y2 - y1)
é 1 ou o peso é 1 e assim P = R2 + (R1 - R2)
, o que simplifica para R1
e é a interpolação linear ao longo da linha inferior apenas.
Agora há o caso de f3
e f5
. Ambos correspondem a (x,y) = (1,1.5)
e (x,y) = (2,1.5)
, respectivamente. Substituindo estes valores por R1
e R2
e P
para ambos os casos dá:
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
Então o que é que isto nos diz? Isto significa que você está interpolando apenas no sentido y. Isto é aparente quando damos uma olhada em P
. Examinando melhor os cálculos de P
para cada um de f3
e f5
, você vê que estamos considerando valores apenas na direção vertical.
Como tal, se você quiser uma resposta definitiva, f1
e f7
são encontrados interpolando ao longo da direção x
/ coluna apenas ao longo da mesma linha. f3
e f5
são encontrados interpolando y
/ direção da linha ao longo da mesma coluna. f4
usa uma mistura de f1
e f7
para calcular o valor final como você já viu.
Para responder a sua pergunta final, f2
, f6
e f8
são preenchidos com base na preferência pessoal. Estes valores são considerados fora dos limites, com os valores x
e y
sendo ambos 2.5
e isso está fora da nossa grelha para
(x,y)
. No MATLAB, a implementação padrão disto é preencher quaisquer valores fora dos limites definidos para não ser um número (NaN
), mas às vezes, as pessoas extrapolam usando interpolação linear, copiam os valores das bordas, ou executam alguns acolchoamentos elaborados como acolchoamento simétrico ou circular. Depende da situação em que você está, mas não há uma resposta correta e definitiva sobre como preencher f2
, f6
e f8
– tudo depende da sua aplicação e do que faz mais sentido para você.
Como bônus, podemos verificar que meus cálculos estão corretos no MATLAB. Primeiro definimos uma grelha de (x,y)
pontos no intervalo , depois redimensionamos a imagem para que seja duas vezes maior onde especificamos uma resolução de 0.5 por ponto em vez de 1. Vou chamar a sua matriz definida de
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
O original (x,y)
grade de pontos se parece com:
>> XX = 1 2 1 2>> YY = 1 1 2 2
A grade expandida para expandir o tamanho da matriz pelo dobro se parece com:
>> 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
é a saída usando X
e Y
como a grade original de pontos e X2
e Y2
são os pontos que queremos interpolar.
obtemos:
>> BB = 100 75 50 NaN 85 60 35 NaN 70 45 20 NaN NaN NaN NaN NaN