Aquí hay un código C # para la transformación de distancia euclidiana al cuadrado 1D según el artículo de Felzenszwald & Huttenlocher :
private static void DistanceTransform(double[] dataInput, ref double[] dataOutput)
{
int n = dataInput.Length;
int k = 0;
int[] v = new int[n];
double[] z = new double[n + 1];
v[0] = 0;
z[0] = Double.NegativeInfinity;
z[1] = Double.PositiveInfinity;
double s;
for (int q = 1; q < n; q++)
{
while (true)
{
s = (((dataInput[q] + q * q) - (dataInput[v[k]] + v[k] * v[k])) / (2.0 * q - 2.0 * v[k]));
if (s <= z[k])
{
k--;
}
else
{
break;
}
}
k++;
v[k] = q;
z[k] = s;
z[k + 1] = Double.PositiveInfinity;
}
k = 0;
for (int q = 0; q < n; q++)
{
while (z[k + 1] < q)
{
k++;
}
dataOutput[q] = ((q - v[k]) * (q - v[k]) + dataInput[v[k]]);
}
}
Esto se puede usar fácilmente para imágenes binarias y en escala de grises aplicándolas primero en columnas de imagen y luego en filas (o viceversa, por supuesto).
La transformación es de hecho muy rápida.
Aquí están las imágenes de origen y salida:
Los píxeles negros tienen el valor 0 y los blancos tienen un valor grande (deben ser mayores que la distancia al cuadrado más grande posible en las imágenes pero no infinito) para que la transformación devuelva la distancia de los píxeles negros y se omitan los blancos.
Para obtener una verdadera transformación de distancia euclidiana, simplemente tome una raíz cuadrada de cada píxel de la imagen de salida.