Methods A & B: Learn the Shape of the Space
The first approaches: learn a small model of the curvature, then do standard trilateration in the corrected space. Both train on random LAB pairs using the public CIEDE2000 formula — no database.
Method A. Metric Tensor (36 parameters)
At any point in color space, distance can be locally approximated by a metric tensor — a 3×3 matrix that says how much each direction costs:
\[ d(a, b) \approx \sqrt{(a-b)^T \cdot G(\text{midpoint}) \cdot (a-b)} \]
I model \(G\) as varying linearly with position: four symmetric 3×3 matrices, 36 parameters total.
\[ \begin{array}{cc} \underset{\text{\scriptsize base}}{G_0} = \left[\begin{array}{rrr} \cellcolor[rgb]{1.000,0.720,0.600}\phantom{-}0.835 & \cellcolor[rgb]{0.997,0.999,1.000}-0.006 & \cellcolor[rgb]{0.996,0.999,1.000}-0.008 \\ \cellcolor[rgb]{0.997,0.999,1.000}-0.006 & \cellcolor[rgb]{1.000,0.915,0.879}\phantom{-}0.253 & \cellcolor[rgb]{1.000,1.000,1.000}-0.000 \\ \cellcolor[rgb]{0.996,0.999,1.000}-0.008 & \cellcolor[rgb]{1.000,1.000,1.000}-0.000 & \cellcolor[rgb]{1.000,0.952,0.931}\phantom{-}0.143 \end{array}\right] & \underset{\text{\scriptsize lightness}}{G_L} = \left[\begin{array}{rrr} \cellcolor[rgb]{1.000,0.963,0.947}\phantom{-}0.002 & \cellcolor[rgb]{1.000,0.832,0.760}\phantom{-}0.009 & \cellcolor[rgb]{1.000,0.757,0.653}\phantom{-}0.013 \\ \cellcolor[rgb]{1.000,0.832,0.760}\phantom{-}0.009 & \cellcolor[rgb]{1.000,0.720,0.600}\phantom{-}0.015 & \cellcolor[rgb]{0.813,0.930,1.000}-0.007 \\ \cellcolor[rgb]{1.000,0.757,0.653}\phantom{-}0.013 & \cellcolor[rgb]{0.813,0.930,1.000}-0.007 & \cellcolor[rgb]{0.813,0.930,1.000}-0.007 \end{array}\right] \\[1.9em] \underset{\text{\scriptsize green-red}}{G_a} = \left[\begin{array}{rrr} \cellcolor[rgb]{0.963,0.986,1.000}-0.006 & \cellcolor[rgb]{1.000,0.935,0.908}\phantom{-}0.015 & \cellcolor[rgb]{0.938,0.977,1.000}-0.010 \\ \cellcolor[rgb]{1.000,0.935,0.908}\phantom{-}0.015 & \cellcolor[rgb]{1.000,0.720,0.600}\phantom{-}0.065 & \cellcolor[rgb]{0.852,0.945,1.000}-0.024 \\ \cellcolor[rgb]{0.938,0.977,1.000}-0.010 & \cellcolor[rgb]{0.852,0.945,1.000}-0.024 & \cellcolor[rgb]{0.705,0.889,1.000}-0.048 \end{array}\right] & \underset{\text{\scriptsize blue-yellow}}{G_b} = \left[\begin{array}{rrr} \cellcolor[rgb]{1.000,0.986,0.981}\phantom{-}0.012 & \cellcolor[rgb]{0.995,0.998,1.000}-0.003 & \cellcolor[rgb]{1.000,0.993,0.990}\phantom{-}0.006 \\ \cellcolor[rgb]{0.995,0.998,1.000}-0.003 & \cellcolor[rgb]{1.000,0.955,0.935}\phantom{-}0.040 & \cellcolor[rgb]{0.600,0.850,1.000}-0.247 \\ \cellcolor[rgb]{1.000,0.993,0.990}\phantom{-}0.006 & \cellcolor[rgb]{0.600,0.850,1.000}-0.247 & \cellcolor[rgb]{1.000,0.955,0.935}\phantom{-}0.040 \end{array}\right] \end{array} \]
Method B. Learned Embedding (115 parameters)
Alternatively, learn a small neural network that flattens the curved space — map LAB to a new 3D space where Euclidean distance approximates CIEDE2000:
def embed(lab):
h = lab @ W1 + b1 # (3) → (16)
h = relu(h) # nonlinearity
return h @ W2 + b2 # (16) → (3)
115 parameters. In this flattened space, trilateration works better. With 4 probes (5 guesses total), both methods reach 100%. With 3 probes (4 guesses), about 67%.
Respectable. But the models are learning an approximation of the distance function, then trilaterating in the approximate space. What if I used the exact formula instead?