I am tracking an object that is thrown in the air, and this object governs a parabolic pattern. I'm tracking the object through a series of 30 images. I managed to exclude all the background and keep the object apparent, then used its centroid to get its coordinates and plot them. Now I'm supposed to predict where the object is going to fall, so I used polyfit & polyval. The problem is, MATLAB says:
我在跟踪一个抛向空中的物体,这个物体控制着一个抛物线。我通过一系列30张图片来跟踪这个物体。我设法排除了所有的背景,使对象保持可见,然后使用它的质心获得它的坐标并绘制它们。现在我要预测物体下落的位置,所以我用了polyfit和polyval。问题是,MATLAB说
??? Index exceeds matrix dimensions.
? ? ?指数超过矩阵维度。
Now the centroid creates its own structure with a row and two columns. Everytime the object moves in the loop, it updates the first row only.
现在质心用一行和两列创建了自己的结构。每当对象在循环中移动时,它只更新第一行。
Here is part of the code:
以下是部分守则:
For N = 1:30
.
.
.
x = centroid(1,1); % extract first row and column for x
y = centroid(1,2); % extract secnd row and column for x
plot_xy = plot(x,y)
set(plot_xy,'XData',x(1:N),'YData',y(1:N));
fitting = polyfit(x(1:N),y(1:N),2);
parabola = plot(x,nan(23,1));
evaluate = polyval(fitting,x);
set(parabola,'YData',evaluate)
.
.
end
The error message I get is:
我得到的错误信息是:
??? Index exceeds matrix dimensions.
? ? ?指数超过矩阵维度。
It seems that (1:N) is causing the problems. I honestly do not know why, but when I remove N, the object is plotted along with its points, but polyfitting won't work. It gives me an error saying:
看来(1:N)是造成问题的原因。老实说,我不知道为什么,但是当我移除N时,对象和它的点一起被绘制,但是polyfitting不起作用。它给了我一个错误的说法:
Warning: Polynomial is not unique; degree >= number of
data points.
> In polyfit at 72
If I made it (1:N-1) or something, it plots more points before it starts giving me the same error (not unique ...). But I can't remove (1:N), because I have to evaluate the coefficients of the polynomial in each loop (each value of N), so what's the solution?
如果我做了(1:N-1)或别的什么,它会在开始给我同样的错误(不是唯一的…)之前绘制更多的点。但是我不能去掉(1:N)因为我要计算每个循环中多项式的系数(N的每个值)那么解是什么呢?
Edit 2 :
编辑2:
This is more of my code
这是我的代码
for N = 1:30
hold on
I = figure.image.(['j' num2str(N)]);
bw = (I);
imshow(bw)
ss = bwlabel(bw);
s = regionprops(bw,'centroid');
centroids = cat(1, s.Centroid);
hold(imgca,'on')
plot(imgca,centroids(1,1), centroids(1,2),'r*')
x = centroids(1,1);
y = centroids(1,2);
points = plot(x,y,'bo',x,y,'rx');
hold on;
for N>3
C1 = centroids(1,1);
C2 = centroids(1,2);
set(points,'XData',C1,'YData',C2);
poly = polyfit(C1,C2,2);
parabola = plot(C1,nan(size(centroids,1),1));
pval = polyval(poly,x);
set(parabola,'YData',pval);
pause(0.5)
end
end
Edit 3
编辑3
Code to display object distination:
显示对象膨胀的代码:
poly = polyfit(C1,C2,2);
g = roots(poly);
v = max(g)
plot(xPlot,polyval(poly,xPlot),'y')
plot(v,'go')
The parabola line is plotted correctly due to xPlot, but for g
(the prediction), it all goes wrong... Am I using the wrong syntax to get the max value?
由于xPlot的关系,抛物线被正确绘制出来,但是对于g(预测)来说,这一切都是错误的……我是否使用了错误的语法来获取最大值?
Alt text http://img706.imageshack.us/img706/6343/parabolaaaaa.jpg
Alt文本http://img706.imageshack.us/img706/6343/parabolaaaaa.jpg
I also realized if I put plot(g,'g--')
instead of v, I get: Wonder if I can get this horizontal instead of vertical. Then I will have a line with a circle where the parabola is predicted to stop.
我也意识到,如果我画出图(g, g,)而不是v,我得到:不知道我能不能得到这个水平的而不是垂直的。然后我有一条直线,它有一个圆预测抛物线会停止。
Alt text http://img101.imageshack.us/img101/6343/parabolaaaaa.jpg
Alt文本http://img101.imageshack.us/img101/6343/parabolaaaaa.jpg
3 个解决方案
#1
1
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));
#2
1
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:
我怀疑你可能会混淆x和y,没有它们你可能会做得更好。如果我正确理解了您的意图,那么我将重写您的代码。注意,特别是重写的polyfit调用。我也认为你硬编码了对nan的调用,所以我也“更正”了:
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
#3
1
[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).
在这一步之后,C1和C2变成了单元素标量。您可以使用size(C1)和size(C2)检查这个问题,它们将返回[1]作为答案。我猜你想画出第一个C1点和c2点,然后把它一直延伸到元素对n,这是不必要的,这个绘图函数可以处理向量(甚至是矩阵,但它会以一系列的图出现)。
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.
我不熟悉图像处理工具箱,我没有那个工具箱,所以我不能检查函数输出。但就我所知,你需要的是一个30行2列的质心位置数据数组,从中你将曲线拟合它在未知x的位置,我去掉了一些绘图函数;我相信这会使代码更清晰。
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)
.
要得到抛物线在x_i点的y位置,使用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.
特别注意cat函数的正确语法;cat(A,B)将B连接到A下面,不能像在原始代码中那样只使用一个参数。这很可能是你头痛的根本原因,因为MATLAB仅使用一个参数就会使用“s”。将“Centroid”作为新的“Centroid”数组,而不是将其添加到现有的“Centroid”数组之下。
Reply to EDIT #3
回复编辑# 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.
我添加了一些评论。问题是,你调用的这条线用来绘制预期目标;语法似乎是错误的。如果只给出一个数据参数,MATLAB假设给定的数据为y值,使用其数组索引作为x值(即在1处绘制y(1),在2处绘制y(2)等)。这不是变量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 ;)
你也可以像Jonas那样使用plot(v,0, go),但如果外推的多项式值实际上接近于0,再检查一下也无妨;)
#1
1
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));
#2
1
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:
我怀疑你可能会混淆x和y,没有它们你可能会做得更好。如果我正确理解了您的意图,那么我将重写您的代码。注意,特别是重写的polyfit调用。我也认为你硬编码了对nan的调用,所以我也“更正”了:
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
#3
1
[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).
在这一步之后,C1和C2变成了单元素标量。您可以使用size(C1)和size(C2)检查这个问题,它们将返回[1]作为答案。我猜你想画出第一个C1点和c2点,然后把它一直延伸到元素对n,这是不必要的,这个绘图函数可以处理向量(甚至是矩阵,但它会以一系列的图出现)。
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.
我不熟悉图像处理工具箱,我没有那个工具箱,所以我不能检查函数输出。但就我所知,你需要的是一个30行2列的质心位置数据数组,从中你将曲线拟合它在未知x的位置,我去掉了一些绘图函数;我相信这会使代码更清晰。
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)
.
要得到抛物线在x_i点的y位置,使用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.
特别注意cat函数的正确语法;cat(A,B)将B连接到A下面,不能像在原始代码中那样只使用一个参数。这很可能是你头痛的根本原因,因为MATLAB仅使用一个参数就会使用“s”。将“Centroid”作为新的“Centroid”数组,而不是将其添加到现有的“Centroid”数组之下。
Reply to EDIT #3
回复编辑# 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.
我添加了一些评论。问题是,你调用的这条线用来绘制预期目标;语法似乎是错误的。如果只给出一个数据参数,MATLAB假设给定的数据为y值,使用其数组索引作为x值(即在1处绘制y(1),在2处绘制y(2)等)。这不是变量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 ;)
你也可以像Jonas那样使用plot(v,0, go),但如果外推的多项式值实际上接近于0,再检查一下也无妨;)