점 클라우드 딥러닝 시리즈 3 - PointNet/PointNet++ 코드 비교

5748 단어 pointcloud
글은 소개하지 않겠습니다. 여기서는 주로 코드를 말합니다.
PointNet++는 PointNet의 업그레이드 버전으로 주로 국부 정보에 대한 감지 능력을 증가시켰다.코드에 나타나면 변화가 비교적 많다. 우리는 분류를 예로 삼아 이들의 실현 코드를 비교 분석한다.
먼저 PointNet은
 
def get_model(point_cloud, is_training, bn_decay=None):
    """ Classification PointNet, input is BxNx3, output Bx40 """
    batch_size = point_cloud.get_shape()[0].value
    num_point = point_cloud.get_shape()[1].value
    end_points = {}

    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_image = tf.expand_dims(point_cloud_transformed, -1)#         

    net = tf_util.conv2d(input_image, 64, [1,3],
                         padding='VALID', stride=[1,1],
                         bn=True, is_training=is_training,
                         scope='conv1', bn_decay=bn_decay)
    net = tf_util.conv2d(net, 64, [1,1],
                         padding='VALID', stride=[1,1],
                         bn=True, is_training=is_training,
                         scope='conv2', bn_decay=bn_decay)

    with tf.variable_scope('transform_net2') as sc:
        transform = feature_transform_net(net, is_training, bn_decay, K=64)
    end_points['transform'] = transform
    net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)
    net_transformed = tf.expand_dims(net_transformed, [2])

    net = tf_util.conv2d(net_transformed, 64, [1,1],
                         padding='VALID', stride=[1,1],
                         bn=True, is_training=is_training,
                         scope='conv3', bn_decay=bn_decay)
    net = tf_util.conv2d(net, 128, [1,1],
                         padding='VALID', stride=[1,1],
                         bn=True, is_training=is_training,
                         scope='conv4', bn_decay=bn_decay)
    net = tf_util.conv2d(net, 1024, [1,1],
                         padding='VALID', stride=[1,1],
                         bn=True, is_training=is_training,
                         scope='conv5', bn_decay=bn_decay)

    # Symmetric function: max pooling
    net = tf_util.max_pool2d(net, [num_point,1],
                             padding='VALID', scope='maxpool')

    net = tf.reshape(net, [batch_size, -1])
    net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,
                                  scope='fc1', bn_decay=bn_decay)
    net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,
                          scope='dp1')
    net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,
                                  scope='fc2', bn_decay=bn_decay)
    net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,
                          scope='dp2')
    net = tf_util.fully_connected(net, 40, activation_fn=None, scope='fc3')

    return net, end_points

모형은 특징 추출과 분류 두 개의 큰 덩어리로 나눌 수 있다.
 
특징 추출 부분에서 논문에서 묘사한 바와 같이 T-net->mlp(64,64)->T-net->mlp(641281024).먼저 티넷이 점운을 적당한 각도에 놓는 데 사용한다.다음은 두 층conv2d권적층으로 첫 번째(1,3)의 권적핵으로 (B,N,3,1)을 (B,N,1,64)로 바꾸고 두 번째는 전체 연결층에 해당하며 데이터 구조에 영향을 주지 않는다.그 다음에 또 하나의 T-net이 특징의 정렬에 사용된다.그 다음은 3층 mlp로 차원 상승을 통해 특징을 얻는다.피쳐 추출 부분은 여기서 끝냅니다.
다음은 분류 작업 부분, 3개의 전체 연결층, 최종적으로 40개의 분류를 얻었다.
 
PointNet++를 살펴보겠습니다.
 
def get_model(point_cloud, is_training, bn_decay=None):
    """ Classification PointNet, input is BxNx3, output Bx40 """
    batch_size = point_cloud.get_shape()[0].value
    num_point = point_cloud.get_shape()[1].value
    end_points = {}
    l0_xyz = point_cloud
    l0_points = None
    end_points['l0_xyz'] = l0_xyz

    # Set abstraction layers
    # Note: When using NCHW for layer 2, we see increased GPU memory usage (in TF1.4).
    # So we only use NCHW for layer 1 until this issue can be resolved.
    l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=512, radius=0.2, nsample=32, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1', use_nchw=True)
    l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.4, nsample=64, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2')
    l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, mlp=[256,512,1024], mlp2=None, group_all=True, is_training=is_training, bn_decay=bn_decay, scope='layer3')

    # Fully connected layers
    net = tf.reshape(l3_points, [batch_size, -1])
    net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
    net = tf_util.dropout(net, keep_prob=0.5, is_training=is_training, scope='dp1')
    net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
    net = tf_util.dropout(net, keep_prob=0.5, is_training=is_training, scope='dp2')
    net = tf_util.fully_connected(net, 40, activation_fn=None, scope='fc3')

    return net, end_points

PointNet++의 네트워크 구조는 PointNet보다 복잡하다.특징 추출 부분과 분류 작업 부분으로 나눌 수도 있다.
 
특징 추출 부분인 코드의 Set abstraction layers는 T-net을 사용하지 않고 점 구름을 직접 처리한 것을 주의해야 한다.세 개의 Pointnetsa_모듈로 구성되어 있으며 각 모듈에는 3층 mlp와 1개의 pooling층이 포함되어 있어 특징 추출에 총 9개의 mlp층을 사용했습니다.Pointnet 정보sa_module 모듈이 필요하면 블로그를 따로 쓸 수도 있습니다.
분류 작업 섹션은 PointNet과 크게 다르지 않습니다.
 

좋은 웹페이지 즐겨찾기