Ejemplo n.º 1
0
    def test_padded(self, octree: torch.Tensor):

        # Configuration
        depth = self.octree_creator._depth
        channels = 6 if self.octree_creator._include_color else 3
        num_outputs = 5

        # Pad octree to a specific, fixed length
        print(f'Original size: {octree.shape}')
        padded_size = 1000000
        octree_padded = torch.nn.ConstantPad1d(
            (0, padded_size - octree.shape[0]), 0)(octree)

        # Create batch from the octree and move it to VRAM (it has to be in VRAM for the next step)
        octree_batch = ocnn.octree_batch([octree_padded]).cuda()

        # Extract features from the octree
        data = ocnn.octree_property(octree_batch, 'feature', depth).cuda()
        assert data.size(1) == channels

        # Test simple convolution
        conv1 = ocnn.OctreeConv(depth, channels, num_outputs)
        conv1.cuda()
        out1 = conv1(data, octree_batch)

        # Test fast convolution
        conv2 = ocnn.OctreeConvFast(depth, channels, num_outputs)
        conv2.cuda()
        out2 = conv2(data, octree_batch)
Ejemplo n.º 2
0
 def parse_batch(self, batch):
     octree = batch['octree'].cuda()
     if self.FLAGS.LOSS.point_wise:
         points = batch['points']
         pts = ocnn.points_batch_property(points, 'xyzi').cuda()
         label = ocnn.points_batch_property(points,
                                            'label').squeeze().cuda()
     else:
         pts = None
         label = ocnn.octree_property(octree, 'label',
                                      self.FLAGS.MODEL.depth)
         if self.FLAGS.MODEL.nempty:
             child = ocnn.octree_property(octree, 'child',
                                          self.FLAGS.MODEL.depth)
             label = label[child >= 0]
     return octree, pts, label
Ejemplo n.º 3
0
 def test_xyz_key(self):
   samples = ocnn.octree_samples(['octree_1', 'octree_1'])
   octree = ocnn.octree_batch(samples).cuda()
   xyz = ocnn.octree_property(octree, 'xyz', 5)
   key = ocnn.octree_xyz2key(xyz, 5)
   xyz_out = ocnn.octree_key2xyz(key, 5)
   self.assertTrue((xyz == xyz_out).cpu().numpy().all())
Ejemplo n.º 4
0
    def forward(self, octree):
        x = ocnn.octree_property(octree, 'feature', self.depth)
        assert x.size(1) == self.channel_in
        for i in range(len(self.conv_block)):
            x = self.conv_block[i](x, octree)
            x = self.pool_block[i](x, octree)
        x = self.octree2voxel(x)
        # data = self.header(data)
        x = self.drop(x)
        x = self.flat(x)

        x = self.fc(x)
        xskip = x
        x = self.bn(x)
        x = self.relu(x)

        r = random.randint(0, 1)
        if r == 1:

            x = self.mlp1(x)
            xm = x
            x = self.mlp2(x)
            glob_feat, indice = torch.max(xm, 0)
            glob_feat = glob_feat.repeat(x.size()[0], 1)
            concat = torch.cat((xskip, glob_feat), 1)
            x = self.mlp3(concat)

        x = self.drop2(x)
        x = self.fc2(x)
        return x
Ejemplo n.º 5
0
def train():
    model.train()

    running_loss = 0.0
    for i, data in enumerate(train_loader, 0):
        # get the inputs
        octrees = data[0].cuda()
        labels = ocnn.octree_property(octrees, 'label', FLAGS.MODEL.depth)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        logits = model(octrees)
        logits = logits.squeeze().transpose(0, 1)  # N x C
        loss = loss_functions_seg(logits, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 100 == 99:
            tqdm.write('[Train iter: %5d] loss: %.3f' %
                       (i + 1, running_loss / i))
    return running_loss / i
Ejemplo n.º 6
0
def octree_trilinear(data, octree, depth, target_depth):
    xyz = ocnn.octree_property(octree, 'xyz', target_depth)
    xyz = ocnn.octree_decode_key(xyz).float()
    scale = 2.0**(depth - target_depth)
    xyz += torch.cuda.FloatTensor([0.5, 0.5, 0.5, 0.0])
    xyz *= torch.cuda.FloatTensor([scale, scale, scale, 1.0])
    output = octree_trilinear_pts(data, octree, depth, xyz)
    return output
Ejemplo n.º 7
0
 def forward(self, octree):
   data = ocnn.octree_property(octree, 'feature', self.depth)
   assert data.size(1) == self.channel_in
   for i in range(len(self.convs)):
     data = self.convs[i](data, octree)
     data, _ = self.pools[i](data, octree)
   data = self.octree2voxel(data)
   data = self.header(data)
   return data
Ejemplo n.º 8
0
  def test_decode_encode_key(self):
    samples = ocnn.octree_samples(['octree_1', 'octree_1'])
    octree = ocnn.octree_batch(samples).cuda()
    xyz = ocnn.octree_property(octree, 'xyz', 5)
    pts = ocnn.octree_decode_key(xyz)
    xyz_encode = ocnn.octree_encode_key(pts)

    gt = torch.cuda.ShortTensor([
        [16, 16, 16, 0], [16, 16, 17, 0], [16, 17, 16, 0], [16, 17, 17, 0],
        [17, 16, 16, 0], [17, 16, 17, 0], [17, 17, 16, 0], [17, 17, 17, 0],
        [16, 16, 16, 1], [16, 16, 17, 1], [16, 17, 16, 1], [16, 17, 17, 1],
        [17, 16, 16, 1], [17, 16, 17, 1], [17, 17, 16, 1], [17, 17, 17, 1]])
    self.assertTrue((gt == pts).cpu().numpy().all())
    self.assertTrue((xyz_encode == xyz).cpu().numpy().all())
Ejemplo n.º 9
0
    def test_octree_property(self):
        octree = ocnn.octree_batch(ocnn.octree_samples(['octree_1'] *
                                                       2)).cuda()

        # test index
        out = ocnn.octree_property(octree, 'index', 5)
        out_gt = np.array([0] * 8 + [1] * 8)
        self.assertTrue(np.array_equal(out.cpu().numpy(), out_gt))

        # test feature
        out = ocnn.octree_property(octree, 'feature', 5)
        out_gt = np.zeros([3, 16], dtype=np.float32)
        out_gt[:, 0] = 3.0**0.5 / 3.0
        out_gt[:, 8] = 3.0**0.5 / 3.0
        out_gt = np.expand_dims(out_gt, axis=[0, 3])
        self.assertTrue(np.allclose(out.cpu().numpy(), out_gt))

        # test child
        out = ocnn.octree_property(octree, 'child', 5)
        out_gt = np.ones(16) * (-1)
        out_gt[0] = 0
        out_gt[8] = 1
        self.assertTrue(np.array_equal(out.cpu().numpy(), out_gt))
Ejemplo n.º 10
0
    def forward(self, octree):
        """
        Note: input octree must be batch of octrees (created with ocnn)
        """

        aux_obs = octree['aux_obs']
        octree = octree['octree']

        # Extract features from the octree at the finest depth
        data = ocnn.octree_property(octree, 'feature', self._depth)

        # Make sure the number of input channels matches the argument passed to constructor
        assert data.size(1) == self._channels_in, \
            f"Input octree has invalid number of channels. Got {data.size(1)}, expected {self._channels_in}"

        # Pass the data through all convolutional and polling layers
        for i in range(len(self.convs)):
            data = self.convs[i](data, octree)
            data = self.pools[i](data, octree)

        # Last convolution at full_depth
        if self._full_depth_conv1d:
            # Conv1D
            data = self.full_depth_conv(data)
        else:
            # Conv3D
            data = self.full_depth_conv(data, octree)

        # Convert octree at full_depth into a voxel grid
        data = self.octree2voxel(data)

        # Flatten into a feature vector
        data = self.flatten(data)

        # Feed through the last linear layer
        data = self.linear(data)

        # Get a view that merges stacks into a single feature vector (original batches remain separated)
        data = data.view(-1, self.n_stacks * data.shape[-1])

        if self._aux_obs_dim != 0:
            # Feed the data through linear layer
            aux_data = self.aux_obs_linear(aux_obs.view(-1, self._aux_obs_dim))
            # Get a view that merges aux feature stacks into a single feature vector (original batches remain separated)
            aux_data = aux_data.view(-1, self.n_stacks * self._aux_obs_dim)
            # Concatenate auxiliary data
            data = torch.cat((data, aux_data), dim=1)

        return data
Ejemplo n.º 11
0
  def forward(self, octree):
    depth = self.depth
    data = ocnn.octree_property(octree, 'feature', depth)
    assert data.size(1) == self.channel_in

    pool_idx = [None] * (depth + 1)
    for i, d in enumerate(range(depth, 2, -1)):
      data = self.convs[i](data, octree)
      data, pool_idx[d] = self.pools[i](data, octree)

    for i, d in enumerate(range(2, depth)):
      data = self.deconvs[i](data, octree)
      data = self.unpools[i](data, pool_idx[d+1], octree)
    
    data = self.deconv(data, octree)
    data = self.header(data)
    return data
Ejemplo n.º 12
0
def test():
    model.eval()

    accu, mIoU, counter = 0, 0, 0
    for data in test_loader:
        octrees = data[0].cuda()
        labels = ocnn.octree_property(octrees, 'label', FLAGS.MODEL.depth)

        with torch.no_grad():
            logits = model(octrees)
            logits = logits.squeeze().transpose(0, 1)  # N x C

        counter += 1
        accu += accuracy(logits, labels)
        mIoU += IoU_per_shape(logits, labels, FLAGS.LOSS.num_class)

    accu /= counter
    mIoU /= counter
    tqdm.write('[Test] accuracy: %.3f, mIoU: %.3f' % (accu, mIoU))
    return accu, mIoU
Ejemplo n.º 13
0
    def test_octree2colP(self):
        depth = 4
        channel = 5
        stride = [1, 2]
        kernel_size = [[3, 3, 3], [2, 2, 2], [3, 1, 1], [3, 3, 1], [1, 1, 1]]
        samples = ocnn.octree_samples(
            ['octree_1', 'octree_2', 'octree_2', 'octree_1'])
        octree = ocnn.octree_batch(samples).cuda()
        node_num = ocnn.octree_property(octree, 'node_num', depth)
        data_in = torch.rand(1, channel, node_num.item(), 1).cuda()
        data_in = ocnn.octree_depad(data_in, octree, depth)
        data_in1 = data_in.clone().requires_grad_()
        data1 = ocnn.octree_pad(data_in1, octree, depth, 0)
        data_in2 = data_in.clone().requires_grad_()

        # octree2colP = octree2col + depad
        for i in range(len(stride)):
            for j in range(len(kernel_size)):
                out1 = ocnn.octree2col(data1, octree, depth, kernel_size[j],
                                       stride[i], False)
                if stride[i] == 1:
                    ks, height = out1.size(1), out1.size(2)
                    out1 = out1.view(1, -1, height, 1)
                    out1 = ocnn.octree_depad(out1, octree, depth)
                    out1 = out1.view(channel, ks, -1)
                out2 = ocnn.octree2col(data_in2, octree, depth, kernel_size[j],
                                       stride[i], True)

                pesudo_grad = torch.rand(out1.shape,
                                         dtype=out1.dtype,
                                         device=out1.device)
                out1.backward(pesudo_grad, retain_graph=True)
                out2.backward(pesudo_grad, retain_graph=True)

                # check
                self.assertTrue(
                    np.array_equal(out1.detach().cpu().numpy(),
                                   out2.detach().cpu().numpy()))
                self.assertTrue(
                    np.allclose(data_in1.grad.cpu().numpy(),
                                data_in2.grad.cpu().numpy()))
Ejemplo n.º 14
0
    def test_simple(self, octree: torch.Tensor):

        # Configuration
        depth = self.octree_creator._depth
        channels = 6 if self.octree_creator._include_color else 3
        num_outputs = 5

        # Create batch from the octree and move it to VRAM (it has to be in VRAM for the next step)
        octree_batch = ocnn.octree_batch([octree]).cuda()

        # Extract features from the octree
        data = ocnn.octree_property(octree_batch, 'feature', depth).cuda()
        assert data.size(1) == channels

        # Test simple convolution
        conv1 = ocnn.OctreeConv(depth, channels, num_outputs)
        conv1.cuda()
        out1 = conv1(data, octree_batch)

        # Test fast convolution
        conv2 = ocnn.OctreeConvFast(depth, channels, num_outputs)
        conv2.cuda()
        out2 = conv2(data, octree_batch)
Ejemplo n.º 15
0
    def forward_and_backward(self, kernel_size, stride, idx=0):
        depth = 4
        channel = 3
        height = 152
        num_outputs = 5
        octree = ocnn.octree_batch(
            ocnn.octree_samples(['octree_1', 'octree_2']))
        data = np.random.uniform(-1.0, 1.0,
                                 [1, channel, height, 1]).astype('float32')

        # forward
        conv1 = ocnn.OctreeDeconv(depth, channel, num_outputs, kernel_size,
                                  stride)
        conv2 = ocnn.OctreeDeconvFast(depth, channel, num_outputs, kernel_size,
                                      stride)
        conv3 = ocnn.OctreeDeconv(depth, channel, num_outputs, kernel_size,
                                  stride, True)
        conv4 = ocnn.OctreeDeconv(depth, channel, num_outputs, kernel_size,
                                  stride)

        # use the same initialization
        with torch.no_grad():
            conv2.weights.data.copy_(conv1.weights.data)
            conv3.weights.data.copy_(conv1.weights.data)
            conv4.weights.data.copy_(conv1.weights.data)

        # forward - compare OctreeConv and OctreeConvFast
        octree = octree.cuda()
        conv1.cuda()
        data1 = torch.from_numpy(data).cuda().requires_grad_()
        out1 = conv1(data1, octree)

        conv2.cuda()
        data2 = torch.from_numpy(data).cuda().requires_grad_()
        out2 = conv2(data2, octree)

        # forward - compare OctreeConv with nempty = True and False
        conv3.cuda()
        mask3 = ocnn.octree_property(octree, 'child', depth) >= 0
        data3 = torch.from_numpy(data).cuda().requires_grad_()
        tmp3 = data3[:, :, mask3]
        out3 = conv3(tmp3, octree)

        conv4.cuda()
        depth_out = depth if stride == 1 else depth + 1
        mask4 = ocnn.octree_property(octree, 'child', depth_out) >= 0
        data4 = torch.from_numpy(data).cuda().requires_grad_()
        tmp4 = data4 * mask3.unsqueeze(-1).float()
        tmp4 = conv4(tmp4, octree)
        out4 = tmp4[:, :, mask4]

        # backward
        pesudo_grad = torch.rand(out1.shape,
                                 dtype=out1.dtype,
                                 device=out1.device)
        out1.backward(pesudo_grad)
        out2.backward(pesudo_grad)

        pesudo_grad2 = torch.rand(out3.shape,
                                  dtype=out3.dtype,
                                  device=out3.device)
        out3.backward(pesudo_grad2)
        out4.backward(pesudo_grad2)

        # test
        self.assertTrue(
            np.allclose(out1.cpu().detach().numpy(),
                        out2.cpu().detach().numpy(),
                        atol=1e-6))
        self.assertTrue(
            np.allclose(data1.grad.cpu().numpy(),
                        data2.grad.cpu().numpy(),
                        atol=1e-06))
        self.assertTrue(
            np.allclose(conv1.weights.grad.cpu().numpy(),
                        conv2.weights.grad.cpu().numpy(),
                        atol=1e-06))

        self.assertTrue(
            np.allclose(out3.cpu().detach().numpy(),
                        out4.cpu().detach().numpy(),
                        atol=1e-06))
        self.assertTrue(
            np.allclose(data3.grad.cpu().numpy(),
                        data4.grad.cpu().numpy(),
                        atol=1e-06))
        self.assertTrue(
            np.allclose(conv3.weights.grad.cpu().numpy(),
                        conv4.weights.grad.cpu().numpy(),
                        atol=1e-06))
Ejemplo n.º 16
0
    def octree_property(self, on_cuda=True):
        batch_size = 2
        octree = ocnn.octree_batch(
            ocnn.octree_samples(['octree_1'] * batch_size))
        if on_cuda:
            octree = octree.cuda()

        # test index
        out = ocnn.octree_property(octree, 'index', 5)
        out_gt = np.array([0] * 8 + [1] * 8)
        self.assertTrue(np.array_equal(out.cpu().numpy(), out_gt))

        # test feature
        out = ocnn.octree_property(octree, 'feature', 5)
        out_gt = np.zeros([3, 16], dtype=np.float32)
        out_gt[:, 0] = 3.0**0.5 / 3.0
        out_gt[:, 8] = 3.0**0.5 / 3.0
        out_gt = np.expand_dims(out_gt, axis=[0, 3])
        self.assertTrue(np.allclose(out.cpu().numpy(), out_gt))

        # test child
        out = ocnn.octree_property(octree, 'child', 5)
        out_gt = np.ones(16) * (-1)
        out_gt[0] = 0
        out_gt[8] = 1
        self.assertTrue(np.array_equal(out.cpu().numpy(), out_gt))
        # test child from depth=0
        out = torch.cat(
            [ocnn.octree_property(octree, 'child', d) for d in range(1, 6)])
        outs = ocnn.octree_property(octree, 'child')
        self.assertTrue(
            np.array_equal(outs[batch_size:].cpu().numpy(),
                           out.cpu().numpy()))

        # test node number
        nnums = np.array([2, 16, 128, 16, 16, 16])
        nnum_cums = np.array([0, 2, 18, 146, 162, 178, 194])
        node_num = ocnn.octree_property(octree, 'node_num', 5)
        node_nums = ocnn.octree_property(octree, 'node_num')
        node_num_cum = ocnn.octree_property(octree, 'node_num_cum', 5)
        node_nums_cum = ocnn.octree_property(octree, 'node_num_cum')
        self.assertTrue(node_num.item() == nnums[5])
        self.assertTrue(node_num_cum.item() == nnum_cums[5])
        self.assertTrue(np.array_equal(node_nums.cpu().numpy(), nnums))
        self.assertTrue(np.array_equal(node_nums_cum.cpu().numpy(), nnum_cums))

        # test batch_size, depth, full_depth
        self.assertTrue(
            ocnn.octree_property(octree, 'batch_size').item() == batch_size)
        self.assertTrue(ocnn.octree_property(octree, 'depth').item() == 5)
        self.assertTrue(ocnn.octree_property(octree, 'full_depth').item() == 2)
Ejemplo n.º 17
0
def octree_feature(octree, depth, nempty=False):
    output = ocnn.octree_property(octree, 'feature', depth)
    if nempty:
        output = ocnn.nn.octree_depad(output, octree, depth)
    return output
Ejemplo n.º 18
0
import ocnn
import torch
import numpy as np

depth, channel = 5, 3
octree = ocnn.octree_new(batch_size=1, channel=channel, node_dis=False)
octree = ocnn.octree_grow(octree, target_depth=1, full_octree=True)
octree = ocnn.octree_grow(octree, target_depth=2, full_octree=True)
octree_gt = ocnn.octree_samples(['octree_2'])[0].cuda()

for d in range(2, depth + 1):
    child = ocnn.octree_property(octree_gt, 'child', depth=d)
    label = (child > -1).to(torch.int32)
    octree = ocnn.octree_update(octree, label, depth=d, split=1)
    if d < depth:
        octree = ocnn.octree_grow(octree,
                                  target_depth=d + 1,
                                  full_octree=False)

feature = ocnn.octree_property(octree_gt, 'feature', depth)
octree = ocnn.octree_set_property(octree, feature, depth)

print(
    'Please check the output files:`octree_1.octree` and `octree_2.octree`.\n'
    'The MD5 of `octree_1.octree`: FEB7C4AF43669EB0FC62632C71D1C938\n'
    'The MD5 of `octree_2.octree`: D569D5BB23D34795C5FD81397F56275B')
octree_gt.cpu().numpy().tofile('octree_1.octree')
octree.cpu().numpy().tofile('octree_2.octree')