+1  A: 

[Answer edited to reflect updates]

In your code, you used

C1=centroids(1,1);
C2=centroids(1,2);

After this step, C1 and C2 become single-element scalars. You can check this with size(C1) and size(C2), which will return [1 1] as the answer. I'm guessing that you wanted to plot the first C1- and C2-point, then extend it all the way to element pair N. That's not necessary, the plot function can handle vectors (and even matrices, but that will appear as a series of plots).

I'm not familiar with the image processing toolbox, and I do not have that toolbox so I can't check the function outputs. But as far as I can tell, what you need is a 30-row 2-column array of centroid position data, from which you will curve-fit its position at unknown x. I've removed some plotting functions; I trust this will make the code clearer.

for N=1:30
    I = figure.image.(['j' num2str(N)]);
    bw=(I);
    ss = bwlabel(bw);
    s = regionprops(bw,'centroid');
    centroids = cat(1, centroids, s.Centroid); %Concatenate s.Centroid below centroids
end

%At this point, "centroids" should be a 30-by-2 array
size(centroids) % check if the output from this is [30 2]

x=centroids(:,1);
y=centroids(:,2);
poly=polyfit(x,y,2); %poly is a vector of curve-fitted polynomial coefficients
pval=polyval(poly,x); %pval is a vector of curve-fitted values evaluated at x
parabola=plot(x,pval); %plot the parabola

To get the y-position of the parabola at a point x_i, use polyval(poly,x_i).

Note particularly the proper syntax for the cat function; cat(A,B) concatenates B below A, you can't use cat with only one argument, as in your original code. This is likely the root cause of your headache, since with only 1 argument MATLAB simply takes "s.Centroid" as your new "centroids" array instead of adding it below the existing "centroids" array.

Reply to EDIT #3

In this part of your code

poly=polyfit(C1,C2,2); %'poly' is a vector of polynomial coefficients
g=roots(poly); %g solves for polynomial roots
v =max(g) %v is the largest root (assumed to be the expected ground-level destination)
plot(xPlot,polyval(poly,xPlot),'y') %plots polynomial at given x-values

%here, one expects to plot a point for the expected destination.
%the call to the plot function should follow syntax similar to the previous line
plot(v,'go') %plot function has syntax plot(x,y,options)
%therefore it should look like plot(v,polyval(poly,v),'go')

I've added some comments. The problem is with the line where you called plot to plot the expected destination; the syntax seems to be wrong. If only 1 data argument is given, MATLAB assumes the given data to be the y-value, using its array index as the x-value (i.e. plotting y(1) at 1, y(2) at 2, etc). This is not what you want for variable v.

You can also use plot(v,0,'go') as mentioned by Jonas, but it never hurts to double-check if the extrapolated polynomial value is actually near 0 ;)

JS Ng
Thanks for answering.. Im getting an error `Warning: Polynomial is not unique; degree >= number of data points. > In polyfit at 72` ... Why is this happening ?
ZaZu
For which value of N are you getting this error? I'm guessing it would probably be N=1 or N=2. This is simply because you can't do polynomial curve-fitting with only 1 or 2 points, there is insufficient information :)
JS Ng
Yes at N=1 ... as soon as it starts polyfitting basically ... I think its because the centroids store data in one row only .. it overwrites in every loop..For example, I expect to get 23 rows by the end of the code, but all I get is 1 row with the last coordinates of the centroid .. is this why its not working ???
ZaZu
Will do, updating it soon
ZaZu
Looking at the original question again, there's a point I would like to clarify: You have 30 images and hence 30 corresponding centroids. You also mentioned that the "centroid" array creates its own structure with a row and 2 columns? Can you get the "centroid" array created as 30 rows and 2 columns, each row belonging to one image in the sequence?
JS Ng
I want the centroid array to get 30 rows, its not ... I assume thats why its crashing .. I uploaded a big snippet of my code, check it please
ZaZu
Thanks for updating your answer, I will try and work it out from your help :)
ZaZu
Thanks for adding an additional answer, unfortunately I get the point in the middle when I use this way :( Its similar to the picture but higher (above the curve)
ZaZu
Got the code working, thanks
ZaZu
+1  A: 

I suspect that you may be confusing yourself with x and y and you might do better without them. Here's how I would rewrite your code, if I have understood your intentions correctly. Note especially the rewritten polyfit call. I also think that you have hard-coded the call to nan incorrectly, so I have 'corrected' that too:

For N=1:30
.
.
.
plot_xy=plot(centroid(1,1),centroid(1,2))
set(plot_xy,'XData',centroid(:,1),'YData',centroid(:,2); 
fitting=polyfit(centroid(:,1),centroid(:,2),2);
parabola=plot(centroid(:,1),nan(size(centroid,1),1));
evaluate=polyval(fitting,centroid(1,1));
set(parabola,'YData',evaluate)
.
.
end
High Performance Mark
Thanks for replying !!! I did what you mentioned in your code, but I get the same error of polynomial : `Warning: Polynomial is not unique; degree >= number of data points. > In polyfit at 72` ... I just dont get whats up with this polynomial error
ZaZu
Post some sample data, I'll try it if I have time later.
High Performance Mark
+1  A: 

This is how your code should look like, if I correctly understand what you want to do:

%# if there is only one centroid per image, preassign centroid array like this
centroids = zeros(30,1); %# case A

%# if there can be any number of centroids per image, preassign like this
centroids = cell(30,1); %# case B

for N=1:30
    hold on
    I = figure.image.(['j' num2str(N)]);
    bw=(I);
    imshow(bw)
    ss = bwlabel(bw);
    s = regionprops(bw,'centroid');

    %# for case A
    centroids(N,:) = cat(1, s.Centroid);
    %# for case B
    centroids{N} = cat(1,s.Centroid);

    hold(imgca,'on')

    %# case A
    plot(imgca,centroids(N,1), centroids(N,2),'r*')
    %# case B
    if ~isempty(centroids{N})
       plot(imgca,centroids{N}(:,1), centroids{N}(:,2), 'r*');
    end

    %# I don't think the following lines do anything useful
    x=centroids(1,1); 
    y=centroids(1,2); 
    points=plot(x,y,'bo',x,y,'rx');

    %# update plots
    drawnow

   %# you can only do the fitting once you collected all centroids

end

%# case A - do nothing b/c centroids is already numeric
%# case B - catenate centroids to make a numeric array with 2 columns
centroids = cat(1,centroids{:});


    C1=centroids(:,1);
    C2=centroids(:,2);
    %#set(points,'XData',C1,'YData',C2); 
    poly=polyfit(C1,C2,2); 
    %# you can use the output of polyval directly as y-coordinate
    parabola=plot(C1,polyval(poly,C1));
Jonas
The code gives me this error when I run it in case A : `???subscripted assignment dimension mismatch.` in case B, it works perfectly but I got two problems. The x and y you mentioned that may not be useful are actually there to plot each ball's current and previous position and keep it there ... When I comment out x y and their plotting, I get the ball to move and then the parabola is shown AFTER it finishes ... When I keep the x and y + plotting, I get `??? Index exceeds matrix dimensions.` ... any ideas ?
ZaZu
Ok I got the x and y to not show the index exceeds matrix dimensions .. So it works now, all I need to do is put the parabola plotting in a loop so that it shows (live-time) as the object is being plotted along the screen
ZaZu
Okay I got the x and y not to show that index exceeds matrix dimensions .. I just changed how it extracts rows n cols from the array... Now what I need is, whenever a new image is posted (position change when N+1), I want the previous position plotted by x and y to stay ... this works only after the 23 loop is completed via the command `set(points,'XData',C1,'YData',C2);` that you commented out .. but when I put the code you have there that is after the loop, IN my loop of 1 to 23, I get `??? Cell contents reference from a non-cell array object. ` ... any ideas ?`
ZaZu
Okay, this code `centroids = cat(1,centroids{:})` is the one causing the previous error (non-cell array object) .. Im guessing its because of the {:} ??
ZaZu
@zazu: did you check whether you're doing case A or case B? The `cat` line is only for case B
Jonas
@zazu: in case it wasn't clear: If you go with case A (only 1 centroid per image), remove all code labeled `case B`
Jonas
Thanks for replying Jonas, im using Case B ... It works well but as mentioned before, when I put the command in the loop I get that cell contents reference error ...
ZaZu
Oh, now I understand! Yeah, you can't do that. Instead, inside the loop, call `currentCentroid = cat(1,centroids{:})`, and for plot, use `plot(currentCentroid(:,1),currentCentroid(:,2)`. Otherwise, after the first catenation, centroid turns from a cell array into a double, and in the next iteration, Matlab errors because it expects centroids to be a cell array.
Jonas
Okay thank you very much !! I got it to work now .. There is one thing though, I was expecting the parabola (polyfit) line to plot all the way till the end (as a prediction where the ball will fall) just after 3 loops .. why doesnt this happen ? Instead, it just plots a line step by step as the ball is moving (one image to another) ...
ZaZu
@ZaZu: polyval calculates y-points only for the x-points you give to it. Thus, you may want to define a vector `xPlot` that goes from your starting `x` to some large number (or you can redefine it at every iteration to run from the starting `x` to the point where the parabola hits the ground). Then, you plot using `plot(xPlot,polyval(poly,xPlot))`
Jonas
Do i have to replace plot by anything else ? Or can I just add it as an extra code ? Because I made xplot=Centroids(:,1) but that didnt work =\ ***EDIT*** I made xPlot=C2, and the prediction starts plotting from left to right (from where the object hits the ground, going upwards) ... No idea why
ZaZu
EDIT -- Well you said `starting x to some large number`, so I thought ill make xPlot = 1:500 .. Well that worked but the plot is out of range, which I guess is incorrect .. its continuing to plot the parabola even after the hitting point.
ZaZu
It looks like you want to calculate the point where the parabola hits the ground. Since the parabola hits the ground when `y=0`, you can use `roots` (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/roots.html) to find the corresponding x-coordinates (if the target is above ground at `yTarget`, use `roots(poly+[0,0,yTarget])` instead). Since it's a parabola, you know there will be two roots. If you know that the parabola goes from left to right, use `max` to find the root with the largest x-coordinate and store it in `myRoot`. Then you can create `xPlot` as `1:myRoot`.
Jonas
@Jonas, Im kind of confused regarding the code you mentioned, where would I use `max` ?? Do I replace it somewhere in the code ? Because I know that the parabola always goes from right to left in my case.
ZaZu
A parabola has two roots, i.e. two x-values where the y-value of the parabola is zero. You want your vector xPlot to go from, say, 1 to the rightmost root. To find the rightmost root, you take the maximum of the two roots returned by `root`.
Jonas
Oh im sorry I think I got confused to what you're actually talking about, are you referring to plotting the parabola itself ? Because I managed to do that .. I was referring to adding a point ( i.e ----O ) to mark the destination where the parabola ends (predicted location) of the falling object.
ZaZu
You can do that the same way: find the roots of the parabola, select the larger of the two. This is the predicted location of the falling object.
Jonas
I really thank you for keeping up with me all this time, I really appreciate it alot !! Means loads to me !! Plus im learning new code which is always nice :) I have updated the code, please look at the question **EDIT3** , this is my last problem !!
ZaZu
The root is just the x-value. The corresponding y-value is 0. Thus:`plot(v,0,'r*')`
Jonas
Thank you, but it still plots in the middle, using this method, the point is above the curve(but still in the middle) ... whyyyy ?
ZaZu
its alright I got it thanks :D
ZaZu