Operations with arrays in Matlab

2020-04-21 02:12发布

问题:

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.

回答1:

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



回答2:

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(:)))));


回答3:

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.