Анализ 3D-облака точек путем проецирования на 2D-поверхность

У меня есть трехмерное облако точек (XYZ), где Z может быть положением или энергией. Я хочу спроецировать их на 2D-поверхность в сетке n на m (в моей задаче n = m) таким образом, чтобы каждая ячейка сетки имела максимальное значение разность Z, если Z — это позиция, или значение суммирования по Z, если Z — это энергия.

Например, в диапазоне 0 <= (x,y) <= 20 есть 500 точек. Допустим, плоскость xy имеет n-на-m разделов, например. 4-на-4; под которым я подразумеваю, что в обоих направлениях x и y у нас есть 4 раздела с интервалом 5 (чтобы сделать его 20 максимальным. Теперь каждая из этих ячеек должна иметь значение суммы или максимальной разности Z значения те точки, которые находятся в соответствующем столбце в заданной плоскости xy.

Я сделал простой массив XYZ только для теста следующим образом, где в этом случае Z обозначает энергию каждой точки.

n=1;
for i=1:2*round(random('Uniform',1,5))
    for j=1:2*round(random('Uniform',1,5))
        table(n,:)=[i,j,random('normal',1,1)];
        n=n+1;
    end
end

Как это сделать без циклов?


person user2969863    schedule 08.11.2013    source источник


Ответы (2)


Примечания:

  1. все это может быть почти однострочным с помощью python pandas и методов резки.
  2. Я переписал вашу инициализацию случайного облака

Что вы можете сделать, это

  1. разметить сетку xy через meshgrid,
  2. спроецировать облако на xy (простая маргинализация)
  3. найдите ближайшую точку сетки с помощью kd-tree поиска, т. е. пометьте свои данные, связав каждую точку облака с узлом сетки
  4. сгруппируйте данные по меткам и оцените свою локальную статистику (через accumarray).

Вот рабочий пример:

 samples = 500;
 %data extrema
 xl = 0; xr = 1; yl = 0; yr = 1;

 % # grid points
 sz = 20;
 % # new random cloud    
 table = [random('Uniform',xl,xr,[samples,1]) , random('Uniform',yr,yl,[samples,1]), random('normal',1,1,[samples,1])];

 figure; scatter3(table(:,1),table(:,2),table(:,3));

 % # grid construction
 xx = linspace(xl,xr,sz); yy = linspace(yl,yr,sz);
 [X,Y] = meshgrid(xx,yy);
 grid_centers = [X(:),Y(:)];

 x = table(:,1); y = table(:,2); 

 % # kd-tree
 kdtreeobj = KDTreeSearcher(grid_centers);
 clss = kdtreeobj.knnsearch([x,y]); % # classification

 % # defintion of local statistic
 local_stat = @(x)sum(x) % # for total energy
 % local_stat = @(x)max(x)-min(x) % # for position off-set

 % # data_grouping
 class_stat = accumarray(clss,table(:,3),[],local_stat );       
 class_stat_M  = reshape(class_stat , size(X)); % # 2D reshaping

 figure; contourf(xx,yy,class_stat_M,20); 

введите здесь описание изображениявведите здесь описание изображения

person Acorbe    schedule 08.11.2013

Функция accumarray вполне подходит для такого рода задач. Сначала я определяю пример данных:

table = [ 20*rand(1000,1) 30*rand(1000,1) 40*rand(1000,1)]; % random data
x_partition = 0:2:20; % partition of x axis
y_partition = 0:5:30; % partition of y axis

я предполагаю, что

  • Три столбца table представляют x, y, z соответственно.
  • Ни одна точка не имеет x ниже, чем у первого края вашей сетки, или больше, чем у последнего края, и то же самое для y. То есть сетка покрывает все точки.
  • Если бин не содержит значений, результат должен быть NaN (если вам нужно какое-то другое значение заполнения, просто измените последний аргумент accumarray).

Затем:

L = size(table,1);
M = length(x_partition);
N = length(y_partition);
[~, ii] = max(repmat(table(:,1),1,M) <= repmat(x_partition,L,1),[],2);
[~, jj] = max(repmat(table(:,2),1,N) <= repmat(y_partition,L,1),[],2);
ii = ii-1; % by assumption, all values in ii will be at least 2, so we subtract 1
jj = jj-1; % same for jj
result_maxdif = accumarray([ii jj], table(:,3), [M-1 N-1], @(v) max(v)-min(v), NaN);
result_sum = accumarray([ii jj], table(:,3), [M-1 N-1], @sum, NaN);

Примечания к коду:

  • Ключевым моментом является получение ii и jj, которые дают индексы интервалов x и y, в которых находится каждая точка. Я использую repmat для этого. Было бы лучше использовать bsxfun, но он не поддерживает версию @max с несколькими выходами.
  • Результат имеет размер (M-1) x (N-1) (количество ячеек в каждом измерении)
person Luis Mendo    schedule 08.11.2013
comment
+1 к обоим ответам. Приятно видеть, что accumarray используется по-умному. Существует четкая кривая обучения с accumarray, но она открывает двери, как только вы ее освоите. - person chappjc; 09.11.2013
comment
@chappjc Мне нравится, как все эти входные параметры (для накопления массивов), которые я изначально считал почти бесполезными, оказываются именно тем, что мне нужно ;-) - person Luis Mendo; 09.11.2013