1

I have a custom function to calculate the weight between two pixels (that represent nodes on a graph) of an image

function [weight] = getWeight(a,b,img, r, L)
    ac = num2cell(a);
    bc = num2cell(b);
    imgint1 = img(sub2ind(size(img),ac{:})); 
    imgint2 = img(sub2ind(size(img),bc{:}));
    weight = (sum((a - b) .^ 2) + (r^2/L) * abs(imgint2 - imgint1)) / (2*r^2);

where a = [x1 y1] and b = [x2 y2] are coordinates that represents pixels of the image, img is a gray-scale image and r and L are constants. Within the function imgint1 and imgint2 are gray intensities of the pixels on a and b.

I need to calculate the weight among set of points of the image.

Instead of two nested loops, I want to use the pdist function because it is WAY FASTER!

For instance, let nodes a set of pixel coordinates

nodes  =
 1     1
 1     2
 2     1
 2     2

And img = [ 128 254; 0 255], r = 3, L = 255

In order to get these weights, I am using an intermediate function.

function [weight] = fxIntermediate(a,b, img, r, L)

    weight = bsxfun(@(a,b) getWeight(a,b,img,r,L), a, b);

In order to finally get the whole set of weights

distNodes = pdist(nodes,@(XI,XJ) fxIntermediate(XI,XJ,img,r,L));

But it always get me an error

Error using pdist (line 373)
Error evaluating distance function '@(XI,XJ)fxIntermediate(XI,XJ,img,r,L)'.

Error in obtenerMatriz (line 27)
    distNodes = pdist(nodes,@(XI,XJ) fxIntermediate(XI,XJ,img,r,L));

Caused by:
    Error using bsxfun
    Invalid output dimensions.

EDIT 1

This is a short example of my code that it should work, but I got the error mentioned above. If you copy/paste the code on MATLAB and run the code you will see the error

function [adjacencyMatrix] = problem
    img = [123, 229; 0, 45];                % 2x2 Image as example
    nodes  = [1     1;  1     2; 2     2];  % I want to calculate distance function getWeight()
                                            % between pixels img(1,1), img(1,2), img(2,2) 
    r = 3;                                  % r is a constant, doesn't matter its meaning
    L = 255;                                % L is a constant, doesn't matter its meaning

    distNodes = pdist(nodes,@(XI,XJ) fxIntermediate(XI,XJ,img,r,L)); 
    adjacencyMatrix = squareform(distNodes );
end

function [weight] = fxIntermediate(a,b, img, r, L)
    weight = bsxfun(@(a,b) getWeight(a,b,img,r,L), a, b);
end

function [weight] = getWeight(a,b,img, r, L)
    ac = num2cell(a);
    bc = num2cell(b);
    imgint1 = img(sub2ind(size(img),ac{:})); 
    imgint2 = img(sub2ind(size(img),bc{:}));
    weight = (sum((a - b) .^ 2) + (r^2/L) * abs(imgint2 - imgint1)) / (2*r^2);
end

My goal is to obtain an adjacency matrix that represents the distance between pixels. For the above example, the desired adjacency matrix is:

adjacencyMatrix =    
          0         0.2634     0.2641
          0.2634    0          0.4163
          0.2641    0.4163     0
zeellos
  • 139
  • 11
  • 2
    Please provide a a Minimal, Complete, and Verifiable example. see http://stackoverflow.com/help/mcve In particular, values for img, R and L are missing. – A. Donda Apr 11 '15 at 02:42
  • @A.Donda I added values for the other parameters a 2x2 image `img = [ 128 254; 0 255]`, `r = 3`, `L = 55`, I hope it could be clear now. I appreciate if you can help me. – zeellos Apr 12 '15 at 04:03
  • Thanks, but there are still undefined variables: ac and bc. Make the code so we can reproduce your problem, but there's no other problem. :-) – A. Donda Apr 12 '15 at 14:59
  • @A.Donda I'm sorry for the imcomplete information. I edit in order to put de ac, bc variables. I hope It would be more clear, I really need to solve the problem. – zeellos Apr 13 '15 at 17:54
  • zeellos, I still cannot reproduce your problem. Please include in your question one or more code sections corresponding to one or more m-files, that we can copy-and-paste and run, such that it leads to the error you want to solve, and *no other error*. – A. Donda Apr 13 '15 at 18:26
  • Btw., the `pdist` function is only fast because it relies on special efficient implementations of the distance functions. Just because you let `pdist` call your function instead of doing it in a loop won't make it any faster. Maybe it would be better if you post a question about what kind of distance you want to implement and ask about an efficient implementation, instead of asking about problems interfacing with `pdist`. – A. Donda Apr 13 '15 at 18:28
  • @A.Donda I added a block of code that you can copy/paste to MATLAB in order to see the error, also I put the desired result of the block of code. Thank you very much for you help. – zeellos Apr 15 '15 at 01:38
  • Good, I'll have a look. – A. Donda Apr 16 '15 at 01:14

1 Answers1

0

The problem is that you are neither fulfilling the expectations for a function to be used with pdist, nor those for a function to be used with bsxfun.

– From the documentation of pdist:

A distance function must be of form

d2 = distfun(XI,XJ)

taking as arguments a 1-by-n vector XI, corresponding to a single row of X, and an m2-by-n matrix XJ, corresponding to multiple rows of X. distfun must accept a matrix XJ with an arbitrary number of rows. distfun must return an m2-by-1 vector of distances d2, whose kth element is the distance between XI and XJ(k,:).

However, by using bsxfun in fxIntermediate, this function always returns a matrix of values whose size is the larger of the sizes of the two inputs.

– From the documentation of bsxfun:

A binary element-wise function of the form C = fun(A,B) accepts arrays A and B of arbitrary but equal size and returns output of the same size. Each element in the output array C is the result of an operation on the corresponding elements of A and B only. fun must also support scalar expansion, such that if A or B is a scalar, C is the result of applying the scalar to every element in the other input array.

However, your getWeight appears to always return a scalar.

I do not understand your problem well enough in order to repair this. Moreover, I think if speed is what you are after, feeding pdist with a function handle is not the way to go. pdist does not perform magic; it is only fast because its built-in distance functions are implemented efficiently. Also, you are using anonymous function handles and conversions to and from cell arrays, all of which slow the process down. I think you should post a new question where you start with a description of what you are trying to compute, include some code that does the job even if inefficiently, and ask how to improve that.

A. Donda
  • 8,381
  • 2
  • 20
  • 49
  • Thank you for your help,Unfortunately, I didn't get the solution but you help me a lot. It's true that the fxIntermediate return a matrix, I would like to find one way to avoid this intermediate function. By now, I will implement a for-loop version, Thanks – zeellos Apr 27 '15 at 23:46