-
Notifications
You must be signed in to change notification settings - Fork 89
/
Copy pathgetSceneVoxSUNCG.m
145 lines (121 loc) · 6.95 KB
/
getSceneVoxSUNCG.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
function [sceneVox, voxOriginWorld] = getSceneVoxSUNCG(pathToData,sceneId,floorId,roomId,extCam2World)
% Notes: grid is Z up while the The loaded houses are Y up
%{
pathToData = '/n/fs/suncg/data/planner5d/';
sceneId = '000514ade3bcc292a613a4c2755a5050';
floorId = 1;
roomId = 1;
cameraPose = [43.9162 1.64774 50.0449 0.0417627 -0.196116 -0.979691 0.00835255 0.980581 -0.195938 0.55 0.430998 17.8815];
extCam2World = camPose2Extrinsics(cameraPose);
extCam2World = [[1 0 0; 0 0 1; 0 1 0]*extCam2World(1:3,1:3)*[1 0 0; 0 0 1; 0 1 0] extCam2World([1,3,2],4)];
%}
load('suncgObjcategory.mat')
volume_param;
% Compute voxel range in world coordinates
voxRangeExtremesCam = [[-voxSizeCam(1:2).*voxUnit/2;0],[-voxSizeCam(1:2).*voxUnit/2;2]+voxSizeCam.*voxUnit];
voxOriginCam = mean(voxRangeExtremesCam,2);
% Compute voxel grid centers in world coordinates
voxOriginWorld = extCam2World(1:3,1:3)*voxOriginCam + extCam2World(1:3,4) - [voxSize(1)/2*voxUnit;voxSize(2)/2*voxUnit;voxSize(3)/2*voxUnit];
voxOriginWorld(3) = height_belowfloor;
[gridPtsWorldX,gridPtsWorldY,gridPtsWorldZ] = ndgrid(voxOriginWorld(1):voxUnit:(voxOriginWorld(1)+(voxSize(1)-1)*voxUnit), ...
voxOriginWorld(2):voxUnit:(voxOriginWorld(2)+(voxSize(2)-1)*voxUnit), ...
voxOriginWorld(3):voxUnit:(voxOriginWorld(3)+(voxSize(3)-1)*voxUnit));
gridPtsWorld = [gridPtsWorldX(:),gridPtsWorldY(:),gridPtsWorldZ(:)]';
gridPtsLabel = zeros(1,size(gridPtsWorld,2));
house = loadjson(fullfile(pathToData,'house', sceneId,'house.json'));
roomStruct = house.levels{floorId}.nodes{roomId};
floorStruct = house.levels{floorId};
% find all grid in the room
if exist([fullfile(pathToData,'room',sceneId,roomStruct.modelId) 'f.obj'],'file')
floorObj = read_wobj([fullfile(pathToData,'room',sceneId,roomStruct.modelId) 'f.obj']);
inRoom = zeros(size(gridPtsWorldX));
for i = 1:length(floorObj.objects(3).data.vertices)
faceId = floorObj.objects(3).data.vertices(i,:);
floorP = floorObj.vertices(faceId,[1,3])';
inRoom = inRoom|inpolygon(gridPtsWorldX,gridPtsWorldY,floorP(1,:),floorP(2,:));
end
% find floor
floorZ = mean(floorObj.vertices(:,2));
gridPtsObjWorldInd = inRoom(:)'&(abs(gridPtsWorld(3,:)-floorZ) <= voxUnit/2);
[~,classRootId] = getobjclassSUNCG('floor',objcategory);
gridPtsLabel(gridPtsObjWorldInd) = classRootId;
end
% find ceiling
if exist([fullfile(pathToData,'room',sceneId,roomStruct.modelId) 'c.obj'],'file')
ceilObj = read_wobj([fullfile(pathToData,'room',sceneId,roomStruct.modelId) 'c.obj']);
ceilZ = mean(ceilObj.vertices(:,2));
gridPtsObjWorldInd = inRoom(:)'&abs(gridPtsWorld(3,:)-ceilZ) <= voxUnit/2;
[~,classRootId] = getobjclassSUNCG('ceiling',objcategory);
gridPtsLabel(gridPtsObjWorldInd) = classRootId;
end
% Load walls
if exist([fullfile(pathToData,'room',sceneId,roomStruct.modelId) 'w.obj'],'file')
WallObj = read_wobj([fullfile(pathToData,'room',sceneId,roomStruct.modelId) 'w.obj']);
inWall = zeros(size(gridPtsWorldX));
for oi = 1:length(WallObj.objects)
if WallObj.objects(oi).type == 'f'
for i = 1:length(WallObj.objects(oi).data.vertices)
faceId = WallObj.objects(oi).data.vertices(i,:);
floorP = WallObj.vertices(faceId,[1,3])';
inWall = inWall|inpolygon(gridPtsWorldX,gridPtsWorldY,floorP(1,:),floorP(2,:));
end
end
end
gridPtsObjWorldInd = inWall(:)'&(gridPtsWorld(3,:)<ceilZ-voxUnit/2)&(gridPtsWorld(3,:)>floorZ+voxUnit/2);
[~,classRootId] = getobjclassSUNCG('wall',objcategory);
gridPtsLabel(gridPtsObjWorldInd) = classRootId;
end
% Loop through each object and set voxels to class ID
if isfield(roomStruct, 'nodeIndices')
for objId = roomStruct.nodeIndices
object_struct = floorStruct.nodes{objId+1};
if isfield(object_struct, 'modelId')
% Set segmentation class ID
[classRootName,classRootId] = getobjclassSUNCG(strrep(object_struct.modelId,'/','__'),objcategory);
% Compute object bbox in world coordinates
objBbox = [object_struct.bbox.min([1,3,2])',object_struct.bbox.max([1,3,2])'];
% Load segmentation of object in object coordinates
filename= fullfile(pathToData,'object_vox/object_vox_data/',strrep(object_struct.modelId,'/','__'), [strrep(object_struct.modelId,'/','__'), '.binvox']);
[voxels,scale,translate] = read_binvox(filename);
[x,y,z] = ind2sub(size(voxels),find(voxels(:)>0));
objSegPts = bsxfun(@plus,[x,y,z]*scale,translate');
% Convert object to world coordinates
extObj2World_yup = reshape(object_struct.transform,[4,4]);
objSegPts = extObj2World_yup*[objSegPts(:,[1,3,2])';ones(1,size(x,1))];
objSegPts = objSegPts([1,3,2],:);
% Get all grid points within the object bbox in world coordinates
gridPtsObjWorldInd = gridPtsWorld(1,:) >= objBbox(1,1) - voxUnit & gridPtsWorld(1,:) <= objBbox(1,2) + voxUnit & ...
gridPtsWorld(2,:) >= objBbox(2,1) - voxUnit & gridPtsWorld(2,:) <= objBbox(2,2) + voxUnit & ...
gridPtsWorld(3,:) >= objBbox(3,1) - voxUnit & gridPtsWorld(3,:) <= objBbox(3,2) + voxUnit;
gridPtsObjWorld = gridPtsWorld(:,find(gridPtsObjWorldInd));
% If object is a window or door, clear voxels in object bbox
[~,wallId] = getobjclassSUNCG('wall',objcategory);
if classRootId == 4 || classRootId == 5
gridPtsObjClearInd = gridPtsObjWorldInd&gridPtsLabel==wallId;
gridPtsLabel(gridPtsObjClearInd) = 0;
end
% Apply segmentation to grid points of object
[indices, dists] = multiQueryKNNSearchImpl(pointCloud(objSegPts'), gridPtsObjWorld',1);
objOccInd = find(sqrt(dists) <= (sqrt(3)/2)*scale);
gridPtsObjWorldLinearIdx = find(gridPtsObjWorldInd);
gridPtsLabel(gridPtsObjWorldLinearIdx(objOccInd)) = classRootId;
end
end
end
% Remove grid points not in field of view
extWorld2Cam = inv([extCam2World;[0,0,0,1]]);
gridPtsCam = extWorld2Cam(1:3,1:3)*gridPtsWorld + repmat(extWorld2Cam(1:3,4),1,size(gridPtsWorld,2));
gridPtsPixX = gridPtsCam(1,:).*(camK(1,1))./gridPtsCam(3,:)+camK(1,3);
gridPtsPixY = gridPtsCam(2,:).*(camK(2,2))./gridPtsCam(3,:)+camK(2,3);
invalidPixInd = (gridPtsPixX < 0 | gridPtsPixX >= 640 | gridPtsPixY < 0 | gridPtsPixY >= 480);
gridPtsLabel(find(invalidPixInd)) = 0;
% Remove grid points not in the room
gridPtsLabel(~inRoom(:)&gridPtsLabel(:)==0) = 255;
% Change coordinate axes XYZ -> YZX
extSwap = [0,1,0;0,0,1;1,0,0];
[gridPtsX,gridPtsY,gridPtsZ] = ind2sub(voxSize,1:size(gridPtsLabel,2));
gridPts = [gridPtsX(:),gridPtsY(:),gridPtsZ(:)]';
gridPts = extSwap(1:3,1:3) * gridPts;
gridPtsLabel(sub2ind(voxSizeTarget,gridPts(1,:)',gridPts(2,:)',gridPts(3,:)')) = gridPtsLabel;
% Save the volume
sceneVox = reshape(gridPtsLabel,voxSizeTarget');