So, I put some of my pseudo-code into actual code:
program new;
function cts3comp(r1, g1, b1, r2, g2, b2: Integer): extended;
var
XYZ1, XYZ2: array [0..2] of extended;
i: Integer;
dot: Extended;
norm: Extended;
dist: Extended;
begin
RGBToXYZ(r1, g1, b1, XYZ1[0], XYZ1[1], XYZ1[2]);
RGBToXYZ(r2, g2, b2, XYZ2[0], XYZ2[1], XYZ2[2]);
{
Works with the projection formula of vectors onto subspaces in R3.
}
// compute c1 . c2
for i := 0 to 2 do
dot := dot + (XYZ1[i] * XYZ2[i]);
// compute the norm of c2.
for i := 0 to 2 do
norm := norm + sqr(XYZ1[i]);
norm := sqrt(norm);
if (norm = 0) then
norm := 1;
// ||proj|| = (c1 . c2) / ||c2||
dist := dot / norm;
Result := dist;
end;
begin
Writeln(cts3comp(209,210,212, 207,208,210));
Writeln( cts3comp(209,210,212, 209,210,212));
end.
The issue is that it returns:
1.1162714789800413E+0002
1.1404861804534232E+0002
That is essentially the tolerance between them. That being said, a logarithmic scale could almost be used here.
For best results, perhaps divide by a number to make the numbers slightly more reasonable.
E:
Simba is currently running this:
for c1 := clBlack to clWhite do
begin
ColorToRGB(c1, r1, g1, b1);
for c2 := clBlack to clWhite do
begin
colorToRGB(c2, r2, g2, b2);
v := cts3comp(r1, g1, b1, r2, g2, b2);
max := MaxE(max, v);
min := MinE(min, v);
end;
end;
I will post the results when they return.
E3: So, the time for that would have been… well rediculous.
I went and started fidgetting:
program new;
function dotprod(x, y: array of Extended): extended;
var
i, l: Integer;
begin
l := high(x);
for i := 0 to l do
result := result + (x[i]*y[i]);
end;
function normproj(x, onto: array of Extended): extended;
var
i, l: Integer;
dot: Extended;
norm: Extended;
begin
{
Works with the projection formula of vectors onto subspaces in Rn.
}
l := high(x);
// compute c1 . c2
dot := dotprod(x, onto);
// compute the norm of c2.
for i := 0 to l do
norm := norm + sqr(onto[i]);
if (norm = 0) then
norm := 1
else
norm := sqrt(norm);
// ||proj|| = (c1 . c2) / ||c2||
Result := dot / norm;
end;
function cts3comp(r1, g1, b1, r2, g2, b2: Integer): extended;
var
XYZ1, XYZ2: array [0..2] of extended;
rgbnorm: extended;
numerator, denominator: extended;
begin
RGBToXYZ(r1, g1, b1, XYZ1[0], XYZ1[1], XYZ1[2]);
RGBToXYZ(r2, g2, b2, XYZ2[0], XYZ2[1], XYZ2[2]);
//rgbnorm := normproj([r1, g1, b1], [r2, g2, b2]);
//writeln(Format('rgbnorm: %e', [sqrt(dotprod([r1, g1, b1], [r2, g2, b2]) / sqrt(dotprod([r2, g2, b2], [r2, g2, b2]) * dotprod([r1, g1, b1], [r2, g2, b2])))]));
numerator := dotprod(XYZ1, XYZ2);
denominator := sqrt(dotprod(XYZ1, XYZ1) * dotprod(XYZ2, XYZ2));
if (denominator = 0) then
Result := numerator
else
Result := numerator / denominator;
Result := sqrt(result);
//writeln(Format('xyznorm: %e', [Result]));
//Result := normproj(XYZ1, XYZ2);
end;
var
c1, c2: integer;
r1, r2, g1, g2, b1, b2: byte;
i, j: Integer;
max, min, v: extended;
x, y, z: extended;
begin
{ for c1 := clBlack to clWhite do
begin
ColorToRGB(c1, r1, g1, b1);
for c2 := clBlack to clWhite do
begin
colorToRGB(c2, r2, g2, b2);
v := cts3comp(r1, g1, b1, r2, g2, b2);
max := MaxE(max, v);
min := MinE(min, v);
end;
end; }
{ Writeln('Max:');
Writeln(max);
Writeln('Min:');
Writeln(min); }
rgbtoxyz(0, 1, 0, x, y, z);
writeln([x, y, z]);
Writeln(format('similar: %e', [cts3comp(209,210,212, 207,208,210)]));
Writeln(format('same: %e', [cts3comp(209,210,212, 209,210,212)]));
Writeln(format('very different: %e', [cts3comp(1,0,0, 255,255,255)]));
Writeln(format('very different: %e', [cts3comp(255,255,255, 0,0,1)]));
end.
ignore
program new;
function dotprod(x, y: array of Extended): extended;
var
i, l: Integer;
begin
l := high(x);
for i := 0 to l do
result := result + (x[i]*y[i]);
end;
function normproj(x, onto: array of Extended): extended;
var
i, l: Integer;
dot: Extended;
norm: Extended;
begin
{
Works with the projection formula of vectors onto subspaces in Rn.
}
l := high(x);
// compute c1 . c2
dot := dotprod(x, onto);
// compute the norm of c2.
for i := 0 to l do
norm := norm + sqr(onto[i]);
if (norm = 0) then
norm := 1
else
norm := sqrt(norm);
// ||proj|| = (c1 . c2) / ||c2||
Result := dot / norm;
end;
function cts3comp(r1, g1, b1, r2, g2, b2: Integer): extended;
var
XYZ1, XYZ2: array [0..2] of extended;
rgbnorm: extended;
numerator, denominator: extended;
begin
RGBToXYZ(r1, g1, b1, XYZ1[0], XYZ1[1], XYZ1[2]);
RGBToXYZ(r2, g2, b2, XYZ2[0], XYZ2[1], XYZ2[2]);
//rgbnorm := normproj([r1, g1, b1], [r2, g2, b2]);
//writeln(Format('rgbnorm: %e', [sqrt(dotprod([r1, g1, b1], [r2, g2, b2]) / sqrt(dotprod([r2, g2, b2], [r2, g2, b2]) * dotprod([r1, g1, b1], [r2, g2, b2])))]));
numerator := dotprod(XYZ1, XYZ2);
denominator := sqrt(dotprod(XYZ1, XYZ1) * dotprod(XYZ2, XYZ2));
if (denominator = 0) then
Result := numerator
else
Result := numerator / denominator;
Result := sqrt(result);
Writeln(Format('log 2: %e', [ln(result)]));
//writeln(Format('xyznorm: %e', [Result]));
//Result := normproj(XYZ1, XYZ2);
end;
var
c1, c2: integer;
r1, r2, g1, g2, b1, b2: byte;
i, j: Integer;
max, min, v: extended;
x, y, z: extended;
begin
{ for c1 := clBlack to clWhite do
begin
ColorToRGB(c1, r1, g1, b1);
for c2 := clBlack to clWhite do
begin
colorToRGB(c2, r2, g2, b2);
v := cts3comp(r1, g1, b1, r2, g2, b2);
max := MaxE(max, v);
min := MinE(min, v);
end;
end; }
{ Writeln('Max:');
Writeln(max);
Writeln('Min:');
Writeln(min); }
rgbtoxyz(0, 1, 0, x, y, z);
writeln([x, y, z]);
Writeln(format('similar: %e', [cts3comp(209,210,212, 207,208,210)]));
Writeln(format('same: %e', [cts3comp(209,210,212, 209,210,212)]));
Writeln(format('very different: %e', [cts3comp(1,0,0, 255,255,255)]));
Writeln(format('very different: %e', [cts3comp(255,255,255, 0,0,1)]));
end.