软件工程应用与实践(10)-Open3D ML(1)

2021SC@SDUSC

open3d

Open3D ML是Open3D的一个扩展,用于3D机器学习任务。它建立在Open3D核心库的基础上,并使用机器学习工具对其进行扩展,以进行3D数据处理。要使用它,需要使用PyTorchTensorFlow安装Open3D,并查看Open3D-ML。

软件工程应用与实践(10)-Open3D ML(1)_第1张图片

后面将对与Open3D-ML相关的python-open3d-ml-tf-python-layers中的代码进行分析

convolutions.py

from ...python.ops import ops
from .neighbor_search import FixedRadiusSearch, RadiusSearch
import tensorflow as tf
import numpy as np

__all__ = ['ContinuousConv', 'SparseConv', 'SparseConvTranspose']
class ContinuousConv(tf.keras.layers.Layer):

连续卷积。这种卷积支持连续的输入和输出点位置。此层实现中定义的卷积

位置:math:`\mathbf x`处的卷积定义为(f*g)(\mathbf x) = \frac{1}{\psi(\mathbf x)} \sum_{i \in \mathcal N(\mathbf x, R)} a(\mathbf x_i, \mathbf x)\; f_i\; g(\Lambda(\mathbf x_i - \mathbf x)).

使用:math:`f`作为输入特征函数,使用:math:`g`作为过滤函数。

输入点是:math:`\mathbf x_i`,输入特性是:math:`f_i`

规范化:math:`\frac{1}{\psi(\mathbf x)}`可以使用**normalize**参数打开。

每邻居值:math:`a(\mathbf x\u i,\mathbf x)`可用于实现窗口函数;以及参见参数**window_function**

用于查找过滤器值的函数:math:`\Lambda`由参数**coordinate_mapping**坐标映射和**interpolation**插值定义。

offset = self.offset

        if inp_importance is None:
            inp_importance = tf.ones((0,), dtype=tf.float32)

        extents = tf.convert_to_tensor(extents)

        return_distances = not self.window_function is None

        if not user_neighbors_index is None and not user_neighbors_row_splits is None:

            if user_neighbors_importance is None:
                neighbors_importance = tf.ones((0,), dtype=tf.float32)
            else:
                neighbors_importance = user_neighbors_importance

            neighbors_index = user_neighbors_index
            neighbors_row_splits = user_neighbors_row_splits

        else:
            if extents.shape.rank == 0:
                radius = 0.5 * extents
                self.nns = self.fixed_radius_search(
                    inp_positions,
                    queries=out_positions,
                    radius=radius,
                    hash_table=fixed_radius_search_hash_table)
                if return_distances:
                    if self.radius_search_metric == 'L2':
                        neighbors_distance_normalized = self.nns.neighbors_distance / (
                            radius * radius)
                    else:  # L1
                        neighbors_distance_normalized = self.nns.neighbors_distance / radius

            elif extents.shape.rank == 1:
                radii = 0.5 * extents
                self.nns = self.radius_search(inp_positions,
                                              queries=out_positions,
                                              radii=radii)

            else:
                raise Exception("extents rank must be 0 or 1")

            if self.window_function is None:
                neighbors_importance = tf.ones((0,), dtype=tf.float32)
            else:
                neighbors_importance = self.window_function(
                    neighbors_distance_normalized)

            neighbors_index = self.nns.neighbors_index
            neighbors_row_splits = self.nns.neighbors_row_splits

该函数用于计算输出特征。

        num_pairs = tf.shape(neighbors_index)[0]
        self._avg_neighbors = tf.dtypes.cast(
            num_pairs, tf.float32) / tf.dtypes.cast(
                tf.shape(out_positions)[0], tf.float32)

        extents_rank2 = extents
        while extents_rank2.shape.rank < 2:
            extents_rank2 = tf.expand_dims(extents_rank2, axis=-1)

        self._conv_values = {
            'filters': self.kernel,
            'out_positions': out_positions,
            'extents': extents_rank2,
            'offset': offset,
            'inp_positions': inp_positions,
            'inp_features': inp_features,
            'inp_importance': inp_importance,
            'neighbors_index': neighbors_index,
            'neighbors_row_splits': neighbors_row_splits,
            'neighbors_importance': neighbors_importance,
            'align_corners': self.align_corners,
            'coordinate_mapping': self.coordinate_mapping,
            'interpolation': self.interpolation,
            'normalize': self.normalize,
        }

        out_features = ops.continuous_conv(**self._conv_values)

        self._conv_output = out_features

        if self.use_dense_layer_for_center:
            self._dense_output = self.dense(inp_features)
            out_features = out_features + self._dense_output

        if self.use_bias:
            out_features += self.bias
        out_features = self.activation(out_features)

        return out_features

    def compute_output_shape(self, inp_features_shape):
        return tf.TensorShape((None, self.filters))

 统计和调试。 

class SparseConv(tf.keras.layers.Layer):

 稀疏卷积。该层计算仅在指定输出位置计算的卷积。该层假定输入和输出点位于规则网格上。

 offset = self.offset
        voxel_size = tf.convert_to_tensor(voxel_size, dtype=inp_positions.dtype)
        if voxel_size.shape.rank != 0:
            raise Exception("voxel_size must be a scalar")

        if inp_importance is None:
            inp_importance = tf.ones((0,), dtype=tf.float32)

        if isinstance(inp_features, tf.RaggedTensor):
            if not (isinstance(inp_positions, tf.RaggedTensor) and
                    isinstance(out_positions, tf.RaggedTensor)):
                raise Exception(
                    "All of inp_positions, inp_features and out_positions must be tf.Tensor, or tf.RaggedTensor"
                )

        hash_table_size_factor = 1 / 64
        self.nns = self.fixed_radius_search(
            inp_positions,
            queries=out_positions - offset * voxel_size,
            radius=self.kernel_size[0] * voxel_size * 0.51,
            hash_table_size_factor=hash_table_size_factor,
            hash_table=fixed_radius_search_hash_table)

        out_positions_split = None
        if isinstance(inp_positions, tf.RaggedTensor):
            inp_positions = inp_positions.values
            inp_features = inp_features.values
            out_positions_split = out_positions.row_splits
            out_positions = out_positions.values
 num_pairs = tf.shape(self.nns.neighbors_index)[0]
        self._avg_neighbors = num_pairs / tf.shape(out_positions)[0]

        extents_rank2 = tf.fill([1, 1], voxel_size * self.kernel_size[0])

        self._conv_values = {
            'filters': self.kernel,
            'out_positions': out_positions,
            'extents': extents_rank2,
            'offset': offset,
            'inp_positions': inp_positions,
            'inp_features': inp_features,
            'inp_importance': inp_importance,
            'neighbors_index': self.nns.neighbors_index,
            'neighbors_importance': tf.ones((0,), dtype=tf.float32),
            'neighbors_row_splits': self.nns.neighbors_row_splits,
            'align_corners': False,
            'coordinate_mapping': 'identity',
            'interpolation': 'nearest_neighbor',
            'normalize': self.normalize,
        }

        out_features = ops.continuous_conv(**self._conv_values)

        self._conv_output = out_features

        if self.use_bias:
            out_features += self.bias
        out_features = self.activation(out_features)

        if out_positions_split is not None:
            out_features = tf.RaggedTensor.from_row_splits(
                values=out_features, row_splits=out_positions_split)

        return out_features

    def compute_output_shape(self, inp_features_shape):
        return tf.TensorShape((None, self.filters))

统计和调试。

class SparseConvTranspose(tf.keras.layers.Layer):

稀疏转置卷积。该层计算转置卷积,仅在指定的输出位置进行计算。

你可能感兴趣的:(python)