1

我正在生成一个包含来自多个来源的数据的散点图,如下所示。

散点图

我希望能够生成一条围绕任意查询点并通过散点图上的点的曲线。最终目标是计算图上线条之间的面积。

我已经实现了使用knnsearch以圆形方式查找点然后应用hampel过滤器来消除噪声的解决方案。在下面的示例中,我在蓝色阴影区域的中间选择了一个点。如您所见,结果远非完美,我需要更精确。

不是那么完美的结果

我正在寻找类似于boundary功能的东西,但要从点云内部工作,而不是从外部工作。

4

2 回答 2

1

最终目标是计算图上线条之间的面积。

我会做不同的事情。只需取图中的任意两条线,用某种数值近似(例如梯形数值积分)计算曲线下的面积,然后减去面积并获得线之间的面积。

于 2016-11-30T16:03:16.297 回答
1

感谢 Trilarion回答中的想法,我能够想出更好的解决方案。

请注意,我使用 YZ 平面而不是 XY 表示法(与机器人坐标系保持一致)。

解决方案

为每组散点数据生成曲线

% Scatter data is in iy and iz vectors.
curve = fit(iy, iz, 'smoothingspline', 'SmoothingParam', 0.5);
% Remove outliers.
fdata = feval(curve, iy);
I = abs(fdata - iz) > 0.5 * std(iz);
outliers = excludedata(iy, iz, 'indices', I);
% Final curve without outliers.
curve = fit(iy, iz, 'smoothingspline', 'Exclude', outliers, 'SmoothingParam', 0.5);

绘制曲线和散点数据

% Color maps generated by MATLAB's colormap function.
h_curve = plot(curve);
set(h_curve, 'Color', color_map_light(i,:));    
scatter(iy, iz, '.', 'MarkerFaceColor', color_map(i,:))

让用户通过选择点来提供输入

用户选择一个点作为查询点,选择两个点作为 Y 轴上的限制点。这是因为有些曲线很接近,但从不相交。

[cs_position.y, cs_position.z] = ginput(1);
[cs_area_limits, ~] = ginput(2);

if cs_area_limits(1) > cs_area_limits(2)
  cs_area_limits = flipud(cs_area_limits);
end

plot_cross_section(cs_position);

最后计算并绘制表面积

本节使用Doresoom 的精彩回答

function [ ] = plot_cross_section(query_point)
%PLOT_CROSS_SECTION Calculates and plots cross-section area.
%   query_point  Query point.

  % Find values on query point's Y on each of the curves.
  z_values = cellfun(@(x, y) feval(x, y),...
    curves, num2cell(ones(size(curves)) * query_point.y))

  % Find which curves are right above and below the query point.
  id_top = find(z_values >= query_point.z, 1, 'first')
  id_bottom = find(z_values < query_point.z, 1, 'last')

  if isempty(id_top) || isempty(id_bottom)      
    return
  end

  % Generate points along curves on the range over Y.
  y_range = cs_area_limits(1):0.1:cs_area_limits(2);
  z_top = feval(curves{id_top}, y_range).';
  z_bottom = feval(curves{id_bottom}, y_range).';

  % Plot area.
  Y = [ y_range, fliplr(y_range) ];
  Z = [ z_top, fliplr(z_bottom) ];
  fill(Y, Z, 'b', 'LineStyle', 'none')
  alpha 0.5
  hold on

  % Calculate area and show to user.
  cs_area = polyarea(Y, Z);
  area_string = sprintf('%.2f mm^2', cs_area);
  text(0, -3, area_string, 'HorizontalAlignment', 'center')
end

结果

结果图片

于 2016-12-01T16:29:36.860 回答