我在插补和/或拟合样条线方面遇到了一些麻烦。我的问题有两个方面。
我手动选择图像上的点,并希望在两者之间插入点。我点击的点是固定的,任何插值必须经过这些点。没有固定数量的积分。一个图像可能有5个,另一个可能有20个(尽管我保持最少5个)。这些点不是均匀分布在需要插值的线上。事实上,大多数时候都有很大的空白需要填补。使用以下各项将所有点记录为x
和y
坐标值:
[x,y] = ginput;
每个(完整)样条线的长度必须为szG
(通常为100)。因此,我计算了x
和y
插值,并且yy
被反转,因为它将叠加在图像上,并且绘图/图像索引相反:
xx = min(x):(max(x)-min(x)-1)/(szG-1):max(x);
yy = max(y):-(max(y)-min(y)-1)/(szG-1):min(y);
然后我用:计算曲线
newX = interp1(y,x,yy, 'cubic');
newY = interp1(x,y,xx, 'cubic');
然而,当我绘制这些时,插值线不会通过初始点。实际上它在很多时候都很遥远。
第二个问题是,通常两个选定的点具有相同的x
或y
值。这意味着我在插值时会出现错误,因为值必须是不同的。
如何确保插值线穿过选定的数据点?此外,如何解决不同的价值问题?
答案 0 :(得分:0)
您遇到的一个问题是您无法正确反转图像坐标。您的轴的原点需要位于左上角,而不是左下角,因此只需取消y
轴不会为您完成工作。您需要确保原点位于左上方,因此您需要采用y
坐标并减去总行数以方便此操作。然而,在不必手动操作的情况下反转坐标的技巧是在图形本身上进行。这样,您就不必担心进行任何计算以反转y
轴。一旦图形打开,只需执行此操作:
axis ij;
要恢复原点位于左下角的原始系统,只需执行以下操作:
axis xy;
但是,如果您使用imshow
来显示图片,那么绝对不需要反转y
坐标,因为当您显示图像时这已经生效(aka引擎盖下呼叫axis ij
。
如果您确实希望自己手动反转坐标,只需执行此操作,假设您的图像存储在im
中:
y = size(im, 1) - y;
此外,您未正确使用interp1
。您可以使用x
和y
指定控制点,并使用xx
作为新的输入坐标。输出将为您提供沿该行插值的新 y
坐标,其中xx
是要插值的查询点。因此,您可以直接使用interp1
的输出作为结果,只需要调用一次。
这是一个可重复的例子。假设你有图像处理工具箱:
im = imread('cameraman.tif');
imshow(im);
[x,y] = ginput(5);
在这里,我选择了5分。请注意,我不需要撤消y
轴,因为imshow
已经为您执行此操作。我选择了这5个坐标:
>> x
x =
23.0000
71.0000
143.0000
200.0000
238.0000
>> y
y =
75
43
27
47
77
现在让我们从这些点开始使用样条:
szG = 100;
xx = min(x):(max(x)-min(x)-1)/(szG-1):max(x);
yy = interp1(x, y, xx, 'cubic');
如果我可以提出一个小问题,您可以使用linspace
通过以下方式对xx
坐标执行相同操作:
xx = linspace(min(x), max(x), szG);
现在让我们显示这些点,其中关键点为蓝色,带有大圆圈,红色是插值线:
hold on;
plot(x, y, 'b.', 'MarkerSize', 16);
plot(xx, yy, 'r');
这就是我得到的:
我得到的要点是通过控制点,这可能是因为你没有正确使用interp1
。现在,解决您有重复点的问题。这对于interp1
来说根本不是很有用,所以我建议过滤掉任何不唯一的2D点,你可以使用unique
函数来做到这一点。具体而言,将x
和y
坐标放入2D数组中,并根据行过滤掉这些点。这样,您就可以消除任何非唯一x
和y
对,以便在interp1
中使用。像这样:
out = unique([x(:) y(:)], 'rows', 'stable');
x = out(:,1);
y = out(:,2);
unique
也有副作用,其中点按排序顺序排列,以便第一列用作排序键。您可能不想要这个,并且您希望保持与点击图形时相同的点数顺序。因此,您需要使用'stable'
标志来确保不会发生这种情况。完成此操作后,x
和y
现在将包含不同坐标,以便在interp1
中使用。
希望这会有所帮助。祝你好运!