PointNet의 input point cloud processing에 대해서
- -
https://github.com/charlesq34/pointnet.git
Point cloud를 input으로 받는 딥러닝 모델을 설계할 때는 항상 고민에 빠지게 되는 지점은 '길이가 모두 다른 point cloud를 어떻게 정규화를 해 줄 것인가?'인 것 같습니다. 길이를 고정해놓고 패딩을 줄 수도 있고, 정규화 네트워크를 하나 더 붙여 줄 수도 있는데, pointnet에서는 input transform net을 통해서 가변 길이의 point cloud를 모델 input tensor의 길이로 바꿔주고 있습니다.
Filetree
pointnet/
├── LICENSE
├── README.md
├── doc/
├── evaluate.py # 모델 평가 스크립트
├── models/ # 핵심 모델 구현
│ ├── pointnet_cls.py # 분류 모델
│ ├── pointnet_seg.py # 세그멘테이션 모델
│ ├── transform_nets.py # 특징 변환 네트워크
│ └── pointnet_cls_basic.py # 기본 분류 모델
├── part_seg/ # 파트 세그멘테이션
│ ├── train.py
│ └── [기타 파트 세그멘테이션 관련 파일들]
├── provider.py # 데이터 로딩/전처리 유틸리티
├── sem_seg/ # 시맨틱 세그멘테이션
│ ├── batch_inference.py
│ ├── model.py
│ ├── train.py
│ └── [기타 시맨틱 세그멘테이션 관련 파일들]
├── train.py # 메인 학습 스크립트
└── utils/ # 유틸리티 함수들
├── tf_util.py # TensorFlow 유틸리티
├── data_prep_util.py # 데이터 전처리 유틸리티
└── [기타 유틸리티 파일들]
T-Net
Input Transform Network
# models/pointnet_cls.py의 get_model 함수
with tf.variable_scope('transform_net1') as sc:
transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)
point_cloud_transformed = tf.matmul(point_cloud, transform)
input_transform_net은 포인트 클라우드의 공간적 변환을 학습하는 네트워크입니다. 이를 통해서 입력에 대해 3x3 transformation matrix를 학습하도록 합니다.
- 입력 : point cloud (BxNx3, B: 배치 크기, N: 점 개수, 3: XYZ 좌표)
- 출력 : 3xK 크기의 transformation matrix (여기서 K=3)
def input_transform_net(point_cloud, is_training, bn_decay=None, K=3):
""" Input (XYZ) Transform Net, input is BxNx3 gray image
Return:
Transformation matrix of size 3xK """
batch_size = point_cloud.get_shape()[0].value
num_point = point_cloud.get_shape()[1].value
input_image = tf.expand_dims(point_cloud, -1)
net = tf_util.conv2d(input_image, 64, [1,3],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='tconv1', bn_decay=bn_decay)
net = tf_util.conv2d(net, 128, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='tconv2', bn_decay=bn_decay)
net = tf_util.conv2d(net, 1024, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='tconv3', bn_decay=bn_decay)
net = tf_util.max_pool2d(net, [num_point,1],
padding='VALID', scope='tmaxpool')
net = tf.reshape(net, [batch_size, -1])
net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,
scope='tfc1', bn_decay=bn_decay)
net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,
scope='tfc2', bn_decay=bn_decay)
with tf.variable_scope('transform_XYZ') as sc:
assert(K==3)
weights = tf.get_variable('weights', [256, 3*K],
initializer=tf.constant_initializer(0.0),
dtype=tf.float32)
biases = tf.get_variable('biases', [3*K],
initializer=tf.constant_initializer(0.0),
dtype=tf.float32)
biases += tf.constant([1,0,0,0,1,0,0,0,1], dtype=tf.float32)
transform = tf.matmul(net, weights)
transform = tf.nn.bias_add(transform, biases)
transform = tf.reshape(transform, [batch_size, 3, K])
return transform
이 네트워크를 통해서 입력 포인트 클라우드의 방향과 위치를 정규화하고 회전, 이동 등의 기하학적 변환에 대해 invariant하도록 전처리를 하게 됩니다.
F-Net
Feature Transform Network
Feature transform network는 input transform network와 유사한 구조를 가지지만, 특징 공간에서의 변환을 학습하는 네트워크입니다.
- 입력 : 특징 맵 (BxNx1xK, B: 배치 크기, N: 점 개수, K: 특징 차원, 기본값은 64)
- 출력 : KxK 크기의 transformation matrix
def feature_transform_net(inputs, is_training, bn_decay=None, K=64):
""" Feature Transform Net, input is BxNx1xK
Return:
Transformation matrix of size KxK """
batch_size = inputs.get_shape()[0].value
num_point = inputs.get_shape()[1].value
net = tf_util.conv2d(inputs, 64, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='tconv1', bn_decay=bn_decay)
net = tf_util.conv2d(net, 128, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='tconv2', bn_decay=bn_decay)
net = tf_util.conv2d(net, 1024, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='tconv3', bn_decay=bn_decay)
net = tf_util.max_pool2d(net, [num_point,1],
padding='VALID', scope='tmaxpool')
net = tf.reshape(net, [batch_size, -1])
net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,
scope='tfc1', bn_decay=bn_decay)
net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,
scope='tfc2', bn_decay=bn_decay)
with tf.variable_scope('transform_feat') as sc:
weights = tf.get_variable('weights', [256, K*K],
initializer=tf.constant_initializer(0.0),
dtype=tf.float32)
biases = tf.get_variable('biases', [K*K],
initializer=tf.constant_initializer(0.0),
dtype=tf.float32)
biases += tf.constant(np.eye(K).flatten(), dtype=tf.float32)
transform = tf.matmul(net, weights)
transform = tf.nn.bias_add(transform, biases)
transform = tf.reshape(transform, [batch_size, K, K])
return transform
이 네트워크는 특징 공간에서 정규화를 수행해 특징의 alignment를 개선하고 더 discriminative한 특징 추출을 할 수 있게 합니다. 따라서 예를 들어 T-Net이 의자가 어느 방향을 향하고 있든 같은 방향으로 정규화시킨다면, F-Net은 의자의 다리, 등받이 등의 부분적인 특징들을 일관되게 정규화하는 네트워크입니다.
그래서 T-Net을 거치고 F-Net을 거치면, T-Net에서는 원본 데이터의 기하학적 변환을 처리하고 F-Net에서 추출된 특징들의 고차원 변환을 처리하는 계층적인 구조를 가집니다.
'Point Cloud' 카테고리의 다른 글
Point Cloud 를 동심원 모양으로 분할하기 (Python) (0) | 2023.07.31 |
---|---|
Point Cloud Descriptor (2) : FPFH, 3DSC, SHOT, NARF (0) | 2023.07.18 |
Point Cloud Descriptor (1) : PFH (0) | 2023.07.15 |
바닥을 찾아보자 - Plane Segmentation (0) | 2023.07.07 |
Point Cloud 를 군집화해보자 - Clustering : K-means, DBSCAN (1) | 2023.07.06 |
소중한 공감 감사합니다