Combine similar points in a point cloud by their mean

I have a set of coordinates x,y,z

where for each value z

there are some similar values x,y

(not the same but similar). This means that when I draw a 3D object, some points are repeated in every frame (for every z), and also these points are slightly shifted because the objects may move a little when receiving data.

In each frame, the number of repeated points can be different. For point position accuracy, I cannot eliminate these duplicate points. I have to combine them at the center of mass and build a 3D object.

Some of my data looks like this where z is incremented by a value of 1 every frame and I get a set of x, y values ​​for it.

211.312500 242.803571 5.000000
213.864407 267.259887 5.000000
211.986111 214.125000 5.000000
224.198864 298.812500 5.000000
233.244444 225.170370 5.000000
238.354067 249.894737 5.000000
240.807692 198.725275 5.000000
247.603922 281.317647 5.000000
251.493671 316.481013 5.000000
260.176796 223.276243 5.000000
269.823529 256.522876 5.000000
276.506073 188.214575 5.000000
276.941176 292.972851 5.000000
286.388060 327.701493 5.000000
291.673684 223.368421 5.000000
302.773913 261.330435 5.000000
309.080189 300.816038 5.000000
315.031746 196.456349 5.000000
331.283784 231.896396 5.000000
338.495327 271.518692 5.000000
345.351064 303.595745 5.000000
362.117647 243.806723 5.000000
185.085714 256.892857 6.000000
193.821918 287.328767 6.000000
192.929293 227.070707 6.000000
210.651163 242.682171 6.000000
211.977654 213.435754 6.000000
213.306122 266.918367 6.000000
214.909091 183.415584 6.000000
224.152941 298.235294 6.000000
223.957746 327.887324 6.000000
233.672131 225.754098 6.000000
240.058091 198.863071 6.000000
238.150943 250.150943 6.000000
244.044586 170.891720 6.000000
246.847561 280.390244 6.000000
250.793651 316.892857 6.000000
263.232143 354.392857 6.000000
272.419643 157.517857 6.000000
275.139423 187.812500 6.000000
285.312217 327.692308 6.000000
304.767606 167.133803 6.000000
313.893519 195.916667 6.000000
317.795238 334.623810 6.000000
330.388430 230.388430 6.000000
337.775510 271.877551 6.000000
345.485294 304.955882 6.000000
355.268456 206.140940 6.000000
362.585635 243.928177 6.000000
372.008850 279.336283 6.000000
184.281818 255.945455 7.000000
185.614035 201.964912 7.000000
193.048673 286.907080 7.000000
192.668790 227.694268 7.000000
202.280000 316.160000 7.000000
214.126829 184.546341 7.000000
212.371795 212.762821 7.000000
212.763636 266.836364 7.000000
224.266332 298.502513 7.000000
224.325758 327.977273 7.000000
233.230088 349.371681 7.000000
239.947977 199.000000 7.000000
243.050251 170.839196 7.000000
250.298246 317.192982 7.000000
262.468900 354.789474 7.000000
271.629213 156.535581 7.000000
285.615385 328.750000 7.000000
296.467949 358.865385 7.000000
304.243697 165.693277 7.000000
312.126761 196.197183 7.000000
317.313725 334.406863 7.000000
337.482759 177.057471 7.000000
344.804598 305.028736 7.000000
354.792929 205.030303 7.000000
362.387500 243.662500 7.000000
371.720000 279.490000 7.000000

      

+3


source to share


1 answer


Okay, I'm guessing a lot, but we'll see.

First, for completeness, your data is (shorthand):

data = [...
211.312500 242.803571 5.000000
...
362.387500 243.662500 7.000000
371.720000 279.490000 7.000000]

      

Then you need to set the threshold, you suggested 1.5 . I would prefer at least 3 .

thresh = 3;

      

Then the algorithm:

%// sort rows, first regarding column 1, then 2
s = sortrows(data,[1 2]);

%// get differences
sdiff = diff([0 0 0; s],1,1);

%// creat mask with threshold
mask = (abs(sdiff(:,1)) < thresh) & (abs(sdiff(:,2)) < thresh);

%// assign indices to "similar" values
subs = cumsum(~mask);

%// calculate the means of similar values
xmean = accumarray(subs,s(:,1),[],@mean)
ymean = accumarray(subs,s(:,2),[],@mean)

%// create new filtered dataset
fdata = [xmean(subs) ymean(subs) s(:,3)]

%// optional: resort data
fdata = sortrows(fdata,3);

      

And the results are, in each case, the point with the largest z

on top:

figure(1)
subplot(121)
scatter(data(:,1),data(:,2),[],data(:,3))
title('unfiltered')
xlim([150,400])
ylim([150,400])
colormap(jet)
subplot(122)
scatter(fdata(:,1),fdata(:,2),[],data(:,3))
title('filtered')
xlim([150,400])
ylim([150,400])

      



enter image description here

Is this what you want? If not, you need to be much clearer and post an example.

As you can see, it is not perfectly filtered for one point, you can fix it by re-executing the algorithm with different sorts:

s = sortrows(data,[2 1]);

      


Edit: as you said you need 5-6 runs, you can use a loop like this:

fdata = data;
for i = 1:5
    shiftvec = circshift([1 2],i,2);
    s = sortrows(fdata,shiftvec);
    sdiff = diff([0 0 0; s],1,1);
    mask = (abs(sdiff(:,1)) < thresh) & (abs(sdiff(:,2)) < thresh);
    subs = cumsum(~mask);
    xmean = accumarray(subs,s(:,1),[],@mean);
    ymean = accumarray(subs,s(:,2),[],@mean);
    fdata = [xmean(subs) ymean(subs) s(:,3)]; 
    fdata = sortrows(fdata,3); 
end

      

End results:

enter image description here

+3


source







All Articles