-
Notifications
You must be signed in to change notification settings - Fork 7
/
shapeseg.m
175 lines (142 loc) · 6.06 KB
/
shapeseg.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
function [Clusters,remainpc] = shapeseg(datapc,shpfilepath,bufferSz,distThreshold,gridSz)
% SHAPESEG
%
% Function to use (polygonal) shapefiles to delimit 3D point cloud area to
% be segmented using the pcsegdist function.
%
% Inputs:
% - datapc: point cloud data, preferably without ground. But it should also
% work with ground present, provided the shapefile is accurate enough
% - shpfilepath: file path to the shapefile with polygons and attributes
% - bufferSz: set buffer size for shapefile polygon
% - distThreshold: set max distance for pcsegdist
% - gridSz: set grid size for merging remaining point clouds. Use the
% resolution as a rule of thumb
%
% Outputs:
% - Clusters: a struct with the individual segmented objects as fields.
% Each field consists of another struct ("Object") which keeps the point
% cloud data as well as any eventual attributes as described in the
% shapefile
% - remainpc: the remaining point cloud after the objects are segmented
%
% (c) Arnadi Murtiyoso (INSA Strasbourg - ICube-TRIO UMR 7357)
clear Clusters;
clear Object;
%Read shapefile data and convert it to native struct
[shapes,objectList,attList]=shpload(shpfilepath);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Parameters that may be modified (for test purposes)
% dthres = 1.0; %set denoising max distance (optional). default is ONE(1.0) sigma
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[numObject,~] =size (objectList);
[numAtt,~] = size (attList);
f = waitbar(0,'Creating individual point cloud clusters...');
for i=1:numObject
%Name of the object
objectNm = objectList(i,1);
%Create buffer around the polyshape, to take into account digitising
%inprecisions
polyout1 = polybuffer(shapes.(objectNm).polyshape,bufferSz,'JointType','miter','MiterLimit',2);
%Check if there are points inside the polygon (boolean)
TFin = isinterior(polyout1,datapc.Location(:,1),datapc.Location(:,2));
%find row numbers for points which are inside the polygon
rows = find(TFin(:,1)==1);
[nbInlier,~] = size (rows);
%initialise array for segmented point cloud
pcdummy=zeros(nbInlier,3);
%transfer the inlier point cloud data into the dummy
for j=1:nbInlier
pcdummy(j,:)=datapc.Location(rows(j,1),:);
end
%transfer to point cloud class
inPc = pointCloud(pcdummy);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Retrieve the outliers outside the shapefile polygon
rows4 = find(TFin(:,1)==0);
[szOut2,~] = size(rows4);
pcdummy4=zeros(szOut2,3);
for n=1:szOut2
pcdummy4(n,:)=datapc.Location(rows4(n,1),:);
end
outPc = pointCloud(pcdummy4);
% figure (100+i)
% pcshow(outPcseg)
% title(strcat('Remaining points from',{' '},objectNm));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%optional: denoising of the inlier point cloud
% inPc = pcdenoise(inPc, 'Threshold', dthres);
% %plot the segmented point clouds
% figure(i)
% pcshow(inPc);
% title(objectNm);
%perform Euclidean segmentation to clean the segmented point cloud
[labels,~] = pcsegdist(inPc,distThreshold);
%Look for unique labels
a = unique(labels);
%...create a table with name of label and frequency
table = [a,histc(labels(:),a)];
%look for the point cloud with the most points after the segmentation
inSeg = max(table(:,2));
%find the index of this largest point cloud in table
rowTable = find(table(:,2)==inSeg);
indexTable = table(rowTable(1,1),1);
%find the index of points with this index in the original point cloud
rows2 = find(labels(:,1)==indexTable);
%initialize dummy array
pcdummy2=zeros(inSeg,3);
%transfer the final result into the dummy
for k=1:inSeg
pcdummy2(k,:)=inPc.Location(rows2(k,1),:);
end
%transfer the dummy to point cloud class
inPcseg = pointCloud(pcdummy2);
%Export segmented point cloud to PLY format
pcwrite(inPcseg,objectNm,'PLYFormat','binary');
%optional: denoising of the inlier point cloud
% inPcseg = pcdenoise(inPcseg, 'Threshold', dthres);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Retrieve the outliers from the pcsegdist process
rows3 = find(labels(:,1)~=indexTable);
[szOut,~] = size(rows3);
pcdummy3=zeros(szOut,3);
for m=1:szOut
pcdummy3(m,:)=inPc.Location(rows3(m,1),:);
end
outPcseg = pointCloud(pcdummy3);
% figure (100+i)
% pcshow(outPcseg)
% title(strcat('Remaining points from',{' '},objectNm));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Plot the clusters individually
figure('name',objectNm)
pcshow(inPcseg);
title(strcat(objectNm,{' '},'after Euclidean segmentation'));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %optional: denoising of the inlier point cloud
% inPcseg = pcdenoise(inPcseg, 'Threshold', dthres);
%
% %Plot the clusters individually
% figure(20+i)
% pcshow(inPcseg);
% title(strcat(objectNm,{' '},'after denoising'));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Create the struct containing cluster info
Object.PtCloud = inPcseg; %cluster's point cloud data
Object.type = shapes.(objectNm).type; %cluster's type (i.e. shapefile name)
%fill the struct with fields from the shapefile's attributes (name,
%length, etc.)
for l=1:numAtt
Object.(attList{l}) = shapes.(objectNm).(attList{l});
end
%Create the struct containing inlier clusters
Clusters.(objectList{i}) = Object;
%Remerge the remaining unsegmented pointclouds
datapc=pcmerge(outPc,outPcseg,gridSz);
waitbar(i/numObject,f)
end
figure('name','RemainPc')
pcshow(datapc)
title('Remaining point cloud')
close(f);
remainpc=datapc;