I have this 2-dimensional array
x=[62,29,64;
63,31,62;
65,29,60;
63,29,62;
63,31,62;];
1st element in each column is R, 2nd is G, 3rd is B from the formula below.
I would like a function to compute the following operation:
So far, my function definition looks like this:
function[distance]=RGB_dist(x,y)
distance=sqrt(sum(((x-y)*[3;4;2]).^2,2));
end
Tested with the matrix above, disp(RGB_dist(x,x))
outputs only zeroes. That must happen because he is calculating the distance between same vectors. How do I do to calculate the distance between any two vector(lines) from my matrix. Any help would be appreciated.
For two arbitrary lines (e.g. line 1 and line 2) do:
RGB_dist(x(1,:), x(2,:))
if you want all the combinations then check out pdist2
. If you don't have the stats toolbox (i.e. no pdist2
) then use nchoosek
to create all possible pairs of rows:
I = nchoosek(1:size(x,1),2);
D = RGB_dist(x(I(:,1),:), x(I(:,2),:))
by the way, if you want to use pdist
or pdist2
then you will have to alter your function to be able to find the distance between one observation and a list of observations in one shot. The easiest way is to replace your -
with bsxfun
like this:
sqrt(sum(((bsxfun(@minus,x,y))*[3;4;2]).^2,2));
then you can go
D = pdist(x, @RGB_dist)
both methods give you
D =
7
1
1
7
6
8
0
2
6
8
or
squareform(D)
ans =
0 7 1 1 7
7 0 6 8 0
1 6 0 2 6
1 8 2 0 8
7 0 6 8 0
But this is probably wrong as this squares after multiplying by the weights. You probably don't want that so I think your final function should look like that in Divakar's answer
You can use bsxfun
twice (once for the subtraction and once for applying the weights):
weights = [3 4 2];
d = squeeze(sqrt(sum(bsxfun(@times, ...
bsxfun(@minus, x.', permute(x, [2 3 1])).^2, weights(:)))));
One approach based on bsxfun
and pdist2
-
%// Input RGB matrix
x=[62,29,64;
63,31,62;
65,29,60;
63,29,62;
63,31,62;];
Wgts = [3 4 2]; %// Weights
weuc = @(XI,XJ,W)(sqrt(bsxfun(@minus,XI,XJ).^2 * W'));
out = pdist2(x,x, @(Xi,Xj) weuc(Xi,Xj,Wgts)) %// output
Output -
out =
0 5.1962 7.6811 3.3166 5.1962
5.1962 0 6.0000 4.0000 0
7.6811 6.0000 0 4.4721 6.0000
3.3166 4.0000 4.4721 0 4.0000
5.1962 0 6.0000 4.0000 0
According to the smart comment posted by @Luis, it seems like in the final step you can use - out = squareform(pdist(x,@(Xi,Xj) weuc(Xi,Xj,Wgts)))
, which might be a bit faster, but no promises as no proper runtime benchmarks were done. The concepts squareform
and pdist
are introduced in Dan's solution, so credit to him for that. But the values seem different, so I am only guessing that the second input to pdist
aren't the same between these two solutions.