用样条线轮廓化你的手(Matlab)

4
我正在尝试编写一个脚本,使用户可以把手放在屏幕上,用ginput点击几个点,然后让MATLAB使用样条曲线生成人手的轮廓。然而,我不太确定如何让样条曲线连接结果点,因为它们当然是由某种参数化描述的。当这些点不应该从左到右连接时,你如何使用MATLAB中内置的样条命令呢?
到目前为止,我的代码并不多,它只创建了一个框并让你点击一些点。
FigHandle = figure('Position', [15,15, 1500, 1500]);
rectangle('Position',[0,0,40,40])
daspect([1,1,1])
[x,y] = ginput;

所以我想我的问题是如何处理x和y,使它们可以按时间顺序连接成样条曲线。(最后,将最后一个与第一个连接起来)


如果你想在点之间使用线性插值,那么非常简单。只需使用 plot(x,y) 即可。否则,你希望这条线如何表现? - Dennis Jaheruddin
3个回答

4

1
+1 这看起来是一个不错的解决方案,但它需要曲线拟合工具箱。仍然很好看到一个不需要该工具箱的答案。 - Dan
嗯,是的,我同意,这个方法非常有效。我自己也有这个工具箱,所以这可能是一个很好的解决方案。谢谢! - user129412

3
我找到了一种替代使用cscvn函数的方法。
使用半弧长参数化,我可以按照以下方式从数组x和y创建样条曲线:
diffx = diff(x);
diffy = diff(y);
t = zeros(1,length(x)-1);
for n = 1:length(x)-1 
    t(n+1) = t(n) + sqrt(diffx(n).^2+diffy(n).^2);
end
tj = linspace(t(1),t(end),300);

xj = interp1(t,x,tj,'spline');
yj = interp1(t,y,tj,'spline');
plot(x,y,'b.',xj,yj,'r-')

这会创建相当不错的轮廓。

这样做的原因是利用平面上的曲线可以通过连接曲线上的有限个点使用线段来近似生成一个多边形路径。我们可以使用此方法将点(x,y)参数化为t的函数。由于我们只有一些点来创建t,因此我们通过在之间添加线性间隔的点来生成更多点。然后,使用函数interp1,找到与这些线性间隔的t值ti相对应的x和y的中间值。


我让它工作了,但是它产生了很多错误。需要初始化t。在Matlab中(diff(x))(n).^2是语法错误。但曲线看起来不错。如果你清理代码并解释为什么它能工作,我会授予奖励! - Dan
嗯,抱歉,那个回答很草率。这就是晚上回答的结果。现在应该没有太多麻烦,我也加了一个简短的解释。 - user129412
谢谢,我仍然不完全理解t(n+1) = t(n) + sqrt(diffx(n).^2+diffy(n).^2);这一行的含义。您能再详细解释一下吗? - Dan
好的,我稍后会回来处理!我需要考虑如何更详细地解释它,但是http://en.wikipedia.org/wiki/Arc_length包含了其要点。这只是那个的近似形式,因为我们没有x和y的解析表达式。 - user129412
是的,我想我已经解决了。它只是使用欧几里得距离来近似曲线上的距离。因为沿着曲线的距离t总是单调递增的,所以xy都可以被插值。这非常聪明。我认为它仍需要更好的解释,但我会在能够颁发赏金时(还需等待4个小时)进行颁发。 - Dan

1
这是一个使用线性插值的示例:从顺序无序的2D点数组中插值轨迹。这应该会得到与plot(x,y)相同的结果。
该文章的思路是循环遍历每个连续的点对,并在这些点之间进行插值。您可能能够将其调整为使用样条曲线,但每次需要给出4个点,这可能会导致问题,因为它们可能会重叠。
要连接起点和终点,请在插值之前执行此操作:
x(end+1) = x(1);
y(end+1) = y(1);

其实我认为你不能这么轻易地将它扩展到样条曲线...但对于线性插值来说,它是可行的,这是一个开始。 - Dan
一个超过3个点的序列可能没有单调递增或递减的方向。因此,我认为这是一条死路。当然,利用四个点来确定中间点之间的线条应该是什么样子的这个总体想法是有效的,但我没有看到一个简单直接的方法来实现它。 - Dennis Jaheruddin
@DennisJaheruddin 我同意。我非常想知道 cscvn 使用的算法是什么。 - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接