[CVPR 2018] VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection

안녕하세요 ! 4번째 x-review 역시 3D Data를 다루는 논문을 읽어보았습니다. 그럼 바로 리뷰 시작하겠습니다.

1. Introduction

3D Object Detection에서는 LiDAR 센서를 통해 2D 이미지와 다르게 물체의 depth 정보까지 얻을 수 있습니다. 하지만 point cloud의 경우, 데이터의 형태가 기본적으로 sparse할 뿐만 아니라 sensor의 위치가 달라지거나 occlusion에 따라서 point가 밀집되어 있는 정도가 달라지게 됩니다. 그래서 기존에는 직접 feature을 찾는 hand crafted feature 추출을 사용하였는데, 가령 point cloud를 투영하고 2D 이미지에서의 특징 추출 방식을 사용하거나 point cloud를 3D voxel grid로 변형한 후 각각의 voxel에서 hand crafted feature를 인코딩하였습니다. 그러나 이러한 방식의 경우 2D 이미지와는 다르게 얻을 수 있었던 3D shape 정보와 detection task에 맞추어진 invariance에 대한 이용을 어렵게 한다는 단점이 존재합니다.

본 논문 이전에 point cloud를 직접적인 input data로 사용하며 포인트별로 특징을 학습하는 딥러닝 기반의 end-to-end network인 PointNet이 등장합니다. PointNet은 input으로 들어오는 모든 point에 대해 feature transformer network를 적용하게 되는데 일반적으로 센서를 통해 얻어지는 point cloud가 100K에 가깝다는 사실을 생각해보면 모든 point를 처리하는데에 많은 계산과 메모리가 요구될 수밖에 없습니다. 또한 3D Detection이 아닌 3D object segmentation 등의 task에서 의미있는 성능을 보였기에 본 논문에서는 3D Detection에서 유의미한 결과를 내보이고, 더 많은 point를 효과적으로 학습에 사용할 수 있도록 feature learning network를 확장하는 것을 목표로 하고 있습니다.

효율적인 Object Detection을 위해 생각해볼 수 있는 방식 중에는 Region proposal network(RPN)이 존재하며 이는 매우 최적화된 알고리즘이라고 할 수 있지만, 요구되는 data의 형태가 point cloud와 같은 sparse한 형태가 아닌 dense한 tensor 데이터 입니다. 하지만 말씀드렸듯이 효과적인 detection 방식 중 하나이기 때문에 저자는 RPN을 사용하고자 하였습니다.

위에서 언급한 목적을 가지고 본 논문에서 제안한 network가 바로 VoxelNet 입니다. VoxelNet은 point cloud로부터 차별적인 feautre 뽑아내고 3D bounding box를 예측하는 과정까지 한번에 통합하여 학습할 수 있는 end-to-end 프레임워크로 논문의 main contribution을 정리하자면 다음과 같습니다.

  1. point cloud을 입력으로 받는 end-to-end 구조의 새로운 3D Object Detection 프레임워크를 제안하였다.
  2. sparse한 point 구조와 voxel grid에 대한 병렬 처리 관점에서 효율적인 구조를 제시한다.
  3. KiTTI benchmark dataset으로 실험을 하여 car, pedestrian, cyclist detection에서 SOTA를 달성하였다.

1.1 Related Work

2. VoxelNet

2.1. VoxelNet Architecture

이제부터 본격적으로 VoxelNet의 구조에 대해 Figure2.를 따라 살펴보도록 하겠습니다. VoxelNet의 주요 구조는 3가지로 먼저 feature을 학습하는 네트워크와, Convolutional middle layers, 그리고 Introduction에서도 언급했던 RPN으로 나눌 수 있습니다.

2.1.1 Feature Learning Network

Figure2를 보면 DxHxW라고 하단에 적혀있는 부분이 있는데, 해당 이미지에서 보이는 것처럼 input data로 point cloud가 주어지면 똑같은 면적으로 나누어진 3차원 voxel 공간으로 나누게 됩니다. voxel이라는 것이 잘 와닿지 않으실 수도 있는데 volume+pixel을 합친 뜻으로 3차원 공간에서의 픽셀이라고 이해해주시면 될 것 같습니다. D, H, W가 각각 Z, Y, X 축으로의 크기라고 가정하면 한 voxel 당 사이즈를v_D, v_H, v_W로 정의할 수 있습니다. 즉 3차원 voxel 공간은 D’ = D/v_D, H’ = H/v_H, W’ = W/v_W으로 partition이 나누어지게 되는것이죠.

partition을 나눈 직후는 단순히 분포되어 있는 point들 위에 자로 그리듯이 grid를 만들어놓은 것 뿐이기 때문에 Grouping을 통해 실제로 각 voxel grid에 point들이 속하도록 할당해야 합니다. Figrue 2.에서 볼 수 있듯이 번호가 매겨져 있는 1, 2, 3, 4번 voxel grid를 보면 각 grid당 point들이 할당되었긴 하지만 1번처럼 point들이 밀집되어 있는 voxel이 있는 반면, 4번처럼 sparse하게 point들이 존재하거나 심지어는 3번처럼 point들이 아예 포함되지 않기도 합니다.

이러한 voxel 간의 point 불균형을 해결해주기 위해서 다음 단계로 Random Sampling을 거치게 됩니다. Grouping 결과를 통해 직관적으로 알 수 있듯이 point cloud를 그대로 사용할 경우 밀집된 부분으로 detection의 편향이 생길 수 있습니다. 해당 문제 뿐만 아니라 LiDAR 센서를 통해 얻을 수 있는 point cloud의 수는 100k에 다다르는데 이 많은 point를 모두 사용할 경우에는 계산과 메모리에 한계가 생길 수 밖에 없습니다. 그래서 미리 T라는 voxel당 존재할 수 있는 최대 포인트 수를 지정해놓고 T 보다 더 많은 point가 배정되어 있는 voxel의 point를 최대 T까지의 point만 존재하도록 random으로 sampling하는 것 입니다. 이로써 연산량을 줄일 수 있고, voxel 사이의 point 불균형을 해소할 수 있으며 학습 시 variation을 높여주는 효과를 가져옵니다.

다음 단계가 논문이 제시하는 main contribution인 VFE layer 입니다. 우선 하나의 voxel grid가 비어있지 않다는 가정하에 grid 내에는 t \leq T개의 point가 존재하며, 각각의 Voxel은 V = \{p_i = [x_i, y_i, z_i, r_i]^T \in \mathbb{R}^4\}_{i=1…t}으로 표현할 수 있습니다. p_ii번째 point의 XYZ 좌표이고 r_i는 LiDAR 센서가 빛을 쏘았을 때 반사되는 시간을 나타냅니다. voxel을 V로 정의하고 나면, V내의 전체 포인트에 대한 중심 좌표 (v_x, v_y, v_z)을 계산합니다. 그리고 모든 point의 좌표를 본래 좌표 + 이 중심 좌표에 대한 상대 좌표로 표현합니다. 즉 어떤 point의 좌표가 (x_i, y_i, z_i, r_i)이면 상대좌표까지 추가한 좌표는 (x_i, y_i, z_i, r_i, x_i - v_x, y_i - v_y, z_i - v_z)가 되는 것이고 이러한 상대좌표를 feature로 삼아 point wise input V = \{\hat{p} = [x_i, y_i, z_i, r_i, x_i - v_x, y_i - v_y, z_i - v_z]^T \in \mathbb{R}^7\}_{i=1…t}을 만들 수 있습니다.

이러한 V_in을 input feature로 하여 fully connected network(FCN)을 통해 한 voxel 내부의 모든 point들의 feature에 대한 feature space로 옮긴 point-wise feature을 얻을 수 있습니다. FCN은 linear layer, batch normalization layer, ReLU layer로 구성되어 있는데, 논문에서는 이 FCN layer을 거침으로써 voxel 내의 surface에 대한 정보를 encoding 할 수 있다고 얘기합니다 .. 여기까지 진행하면 Figure 3.에서의 Point-wise Feature까지 만든 것 입니다. 이제 이 feature을 f_i \in \mathbb{R}^m이라고 정의하고 모든 f_i에 대해 locally aggregated feature f_~ \in \mathbb{R}^m을 얻기 위해서 다음 단계인 Element-wise Maxpooling을 거치면 voxel 내부의 feature들을 aggregate하여 원하는 locally aggregated feature을 형성합니다. 다음으로 Figure 3.에서 보인 것처럼 locally aggregate feature와 FCN을 거친 point-wise feature을 concat하여 하나의 VFE Layer을 거친 output feature을 만들게 됩니다. 여기서 FCN을 거친 feature의 차원을 m으로 정의하였으니 마지막으로 concat을 완료한 output feature의 차원은 2m이 될 것 입니다. 이런 과정을 모든 voxel에 적용하게 되면 V_{out} = \{f^{out}_i\}_{i...t}을 만들게 되고 논문에서 강조하는 것은 한번의 VFE layer을 거치는 것이 아니라 여러 개의 VFE layer을 사용한다는 것으로 이 V_{out}은 다음 layer의 input으로 사용하게 됩니다. 결국 여러 층의 VFE Layer을 통해 point-wise feature와 locally aggregated feature(voxel feature)을 합침으로써 voxel 내 point의 관계와 point들이 만드는 shape 정보를 encoding 할 수 있게 되는 것 입니다.

하지만 이러한 VFE Layer은 말씀드렸듯이 voxel이 비어있지 않은 경우에 사용하는 것인데 point cloud의 특성상 비어있지 않은 voxel의 비율은 전체 10% 이하에 지나지 않습니다. 그렇기 때문에 VFE layer을 통해 얻은 voxel wise feature을 무작정 C\times{}D’\times{}H’\times{}W’사이즈의 4차원 tensor로 표현하는 것은 메모리와 연산량 관점에서 생각해보았을 때 적절하지 않습니다. 그렇기 때문에 feature을 list 형태로 관리하는 sparse tensor로 표현함으로써 backpropagation에서 사용되는 메모리와 연산량을 줄일 수 있습니다.

2.1.2 Convolutional Middle Layers

앞서 Feature Learning Network를 통해 voxel wise feature을 뽑아낸 것은 결국 point 형태 그대로 CNN에 적용하는 것이 힘들기 때문에 voxel 형태로 쪼개어 CNN에 사용하기 용이하게 바꾸는 것을 목적으로 하고 있습니다. 그래서 output으로 출력된 voxel wise feature을 input으로 3D CNN을 수행하는 것이 다음 단계 입니다. convolution layer는 (C_{in}, C_{out}, k, s, p)으로 이루어져 있으며 각각 input 채널, output 채널, kernel size, stride, padding이 되겠죠. 논문에서 가리키는 Convolutional Middle Layer(ConvMD)란 이러한 convolution layer + BN layer + ReLU로 구성되어 있습니다. 차원이 늘어났을 뿐 2D 이미지에서의 CNN과 유사하다고 볼 수 있습니다. ConvMD에서는 voxel wise feature을 합치고 점차적으로 receptive field를 늘려가면서 shape의 context한 정보를 더해가고자 하였습니다.

2.1.3 Region Proposal Network

본 논문에서는 RPN의 구조를 약간 수정하고 이전 과정인 feature learning network와 ConvMD와 RPN을 결합하여 end-to-end 학습이 가능하도록 하였습니다.

RPN 구조의 input은 ConvMD의 ouput feature map으로 Figure 4.에서 명시되어 있듯이 3개의 block으로 구성되어 있습니다. 먼저 각 block의 첫번째 layer는 stride size를 2로 설정하여 feature map의 크기를 절반으로 downsample 합니다. 두번째 layer는 stride size가 1로 이전 layer에서 나온 feature map의 크기를 유지하면서 BN과 ReLU를 거치도록 합니다.

각 block에서 downsample한 feature map들은 모두 같은 크기로 upsampling 후 합쳐져 하나의 high resolution feature map을 형성합니다. 이 feature map을 각각 2D Conv를 수행하여 class score map과 box regression map을 output으로 생성합니다.

이로써 point cloud를 입력으로 사용하여 voxel 형태로 변형한 후 hand crafted 방식이 아닌 VFE layer을 통해 feature을 추출하고 RPN까지 연결하여 end-to-end 방식으로 detection을 수행할 수 있는 pipeline을 형성하게 되었습니다.

2.2. Loss Function

Loss Function에 대해 살펴보기 전에 우선 3D GT Box의 구성을 알아보도록 하겠습니다. 3D GT Box는 (x^g_c, y^g_c, z^g_c, l^g, w^g, h^g, \theta^g)

7개의 파라미터를 가지고 있고 (x^g_c, y^g_c, z^g_c)는 box의 중심 좌표, l^g, w^g, h^g는 각각 length, width, height가 됩니다. \theta^g는 z축에 대한 회전 각도를 나타냅니다. Figure 4.의 최종 output feature map 2개를 살펴보면 class score map은 channel이 2, regression map의 channel은 14로 되어있는데, 이는 각 voxel grid마다 anchor box를 2개씩 사용하여 class score을 매기고, 각 anchor box마다 7개의 Box 파라미터 (x^a_c, y^a_c, z^a_c, l^a, w^a, h^a, \theta^a) 에 대한 regression을 수행하기 때문입니다. 여기서 regression을 수행하기 위해 수식(1)과 같이 GT box와 BBox 사이의 잔차 벡터를 구하여 regression loss를 계산합니다.

식(2)의 classification loss인 L_{cls}를 구하는 것을 보면 p^{pos}_ip^{neg}_j는 각각 a^{pos}_ia^{neg}_j에 대한 softmax 결과값을 나타냅니다. 다시 말해, GT box와의 IOU를 구하여 threshold를 넘었을 시 a^{pos}_i, 넘지 못하였을 경우 a^{neg}_j가 되고 positive anchor box는 1에 가까워지고 negative anchor box는 0에 가까워지게 binary cross entropy loss를 사용하는 것 입니다. positive anchor에 한해 regression loss까지 구하면 전체 Loss Function을 정의할 수 있습니다.

2.3. Efficient Implementation

논문의 또 하나의 main contribution이라고 할 수 있는 sparse한 point cloud와 voxel grid의 병렬적인 사용에 대한 부분 입니다. 여러번 언급한것처럼 point cloud는 sparse한 형태로 되어있어 dense한 tensor 형태를 처리하기에 최적화되어 있는 GPU 환경에서 처리하기에 적합하지 않습니다. 그렇기 때문에 GPU 환경에서의 처리에 적합하도록 dense한 형태로 바꾸어야 하죠. VFE layer에 데이터를 넣기 전 과정을 연관지어 생각해주시면 될 것 같습니다.

우선 K\times{}T\times{}7 shape의 voxel input feature buffer와 K\times{}1\times{}3 shape의 voxel coordinate buffer가 존재합니다. K라고 함은 비어있지 않은 voxel grid의 최대 개수이며, T는 random sampling 파트를 통해 voxel 내에 존재할 수 있는 최대 point 수라는 것을 알고 있습니다. voxel input feature buffer의 channel 수 7은 본래좌표 + 상대좌표로 표현한 좌표값을 의미합니다. input feature buffer에 좌표값이 들어갈 수 있는 기준은 voxel coordinate buffer에 현재 point가 속해있는 voxel이 존재하는지 여부를 확인하고 만약 존재한다면 해당 point 좌표가 feature bufferd의 해당 voxel 위치에 들어갈 수 있는 것 입니다. 그럼 여러 point가 들어있는 voxel은 여러번 등장하게 될테니 voxel의 존재 여부를 판단할 때 이미 voxel coordinate buffer에 그 voxel의 정보가 들어가있는지 없는지까지 파악해주어야 합니다.

4. Experiments

실험에는 KITTI 3D object detection benchmark를 사용하여 Car, Pedestrain, Cyclist에 대한 성능을 확인하였습니다. 각 class에 대해 easy, moderate, hard 3가지 수준으로 평가를 하였는데 평가 기준은 object의 사이즈나 occlusion 등을 고려하였다고 합니다.

또한 end-to-end pipeline에서의 성능을 강조하기 위해서 제안한 feature learning network 대신 기존의 hand crafted 방식을 사용한 베이스라인인 HC-baseline을 함께 제시하였습니다.

4.1. Evaluation on KITTI Validation Set

먼저 KITTI validation set에서의 실험으로, 이전에 존재하는 Method 중 가장 성능이 우수한 MV(BV+FV+RGB) 방법론과 비교해보았을 때 HC-baseline부터 이미 유사한 성능을 보이고 있는 것을 알 수 있습니다. 논문에서도 특히나 LiDAR만을 사용하였을 때도 이전 방법론들의 성능에 근접할 수 있었으며, end-to-end pipeline을 도입한 VoxelNet은 Car에서 Easy, Moderate, Hard 각각에서 10.68%, 2.78%, 6.29%의 향상이 있었음을 강조하였습니다.

4.2. Evaluation on KITTI Test Set

test dataset에서 또한 VoxelNet이 SOTA를 달성하였습니다. 저자는 여기서 한번 더 KITTI benchmark에서의 많은 방법론들이 RGB image 정보와 LiDAR point cloud를 함께 사용하고 있지만 VoxelNet에서는 오로직 LiDAR만을 사용하였다고 거듭 이야기하고 있습니다.

Author: 손 건화

6 thoughts on “[CVPR 2018] VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection

  1. 좋은 리뷰 감사합니다.
    voxel형태로 처리하는 3d detection 방법론들은 연산량때문인지 대부분 sparse tensor형태를 사용한다고 하는 것 같네요.
    혹시 convolutional middle layer의 input으로는 3d cnn을 수행하는데 2d image에서의 cnn과 유사하지만 차원이 늘어난것이다 라고 하셨는데 그럼 kernel이 3이면 3x3x3의 kernel이 convolution 연산을 수행하는 것인가요?
    감사합니다.

    1. 안녕하세요 ! 댓글 감사합니다.

      넵 도경님이 말씀하신 것처럼 논문에서 사용하는 ConvMD는 3차원이기 때문에 kernel이 연산을 수행할 때 k = (k, k , k)가 됩니다.

  2. 안녕하세요. 리뷰 잘 읽었습니다.
    이제 3D에 관심을 가져보는 상황 속 로보틱스 연구원분들의 리뷰는 주에 한 번씩 읽어도 새롭네요.

    1. “효율적인 Object Detection을 위해 생각해볼 수 있는 방식 중에는 Region proposal network(RPN)이 존재하며 이는 매우 최적화된 알고리즘이라고 할 수 있지만”이라고 설명해주셨는데, RPN이 3D object detection에서 왜 최적화된 알고리즘으로 보이는지 설명해주실 수 있을까요? 3D는 데이터의 양만 보아도 연산량 및 연산 속도에 문제가 생길 것 같은데, RPN을 사용하면 더 버거울 수 있다는 생각이 들어 질문합니다.

    2. 2.1.1의 4 번째 문단을 보면, “voxel을 V로 정의하고 나면, V 내 중심을 정하고 Voxel 내 모든 Point에 중심 과의 잔차를 추가하는 모습을 보이는데, 이 때 정하는 중심은 Grid 내 전체 Point에 대한 중심인가요 아니면 이미 샘플링 한 이후의 T 개의 Point에 대한 중심인가요? 전체라면, 혹은 T개의 Point에 대한 중심이라면 이것이 실제적으로 의미하는 바 (왜 이런 방법을 사용했는지)를 설명해주시면 감사합니다.

    3. 2번의 질문에 이어 VFE Layer를 여러번 사용한다고 했는데, 이 때의 입력 V_{in} 또한 업데이트 되나요? 아니라면, 왜 여러번 사용하는지에 대해 궁금합니다.

    4. 음.. 실험단에서 나와있을 줄 알고 질문 안했는데, 궁금하네요. 결국 LiDAR의 특성을 언급하며 3D Point cloud의 Sparse, Unordered 등을 설명하며 Sampling을 설명해주셨는데, 결국 샘플링 기준은 T라는 Threshold밖에 없나요? 이 T는 어떻게 구해지며 T에 따른 성능 차이도 분명 있을 것 같은데, 해당 Ablation study가 없었는지 궁금합니다. 왜냐하면 LiDAR에 따라 초당 300,000 이상의 Data를 수집할 수도 있으며 또한 FoV에 따라 수집할 수 있는 영역 등이 다 달라 샘플링 기준을 산정하는 등이 굉장히 중요해보이는데, 이에 대한 실험적 결과나 혹은 왜 그런 기준을 산정했는지에 대해 저자가 말을 안했는지 궁금합니다.

    좋은 리뷰 잘 읽었습니다. 기초부터 다지는 느낌이라 앞으로도 건화님의 리뷰를 통해 3D를 간접 경험하고자 합니다!

    1. 안녕하세요 ! 댓글 감사합니다.

      1. 논문에서 RPN을 object detection에 매우 최적화된 알고리즘이라고 서술한 이유는 기존의 2D object detection을 기준으로 이야기한 것 입니다. 그렇기 때문에 introduction에서도 dense tensor 데이터가 요구되며 그럼에도 저자가 3D의 sparse한 tensor 형태에서도 사용하고 싶어함을 언급하였던 것 입니다 !
      2. 음 정확히 sampling 이전, 이후 중 어느 point 개수를 기준으로 중심 좌표를 설정했는지는 나와있지 않지만 아무래도 VFE layer 자체가 random sampling 이후에 진행되는 과정이기 때문에 sampling 이후의 point를 기준으로 설정한 것이 아닐까요 ? ? 그리고 이 중심 point가 실제적으로 의미하는바는 .. 제 생각에는 retrieval에서와 비슷한 이유로 잔차 벡터를 구하여 상대적인 좌표를 구하기 위함이라고 생각했습니다 .. 어쨌든 point가 모아져 있는 것은 object일 가능성이 존재하는 것이니 그런 object의 중심을 구하여 그 object를 구성하는 다른 point들이 상대적으로 어떤 곳에 위치하는지를 알기 위함이 아닐지 ..
      3. V_in이 업데이트 된다는 것이 어떤 것을 의미하는지는 정확히 잘 모르겠습니다만 이전 VFE layer의 output이 다음 VFE layer의 input으로 들어가게 됩니다.
      4. 일단 T를 다르게 설정하는 것에 따른 Ablation Study는 없었습니다 .. 다만 KITTI Dataset에 대해 Car / Pedestrain, Cyclist에 대해 각각 다르게 point cloud를 수집한 것에 대해 서술되어 있습니다. Car detection의 경우 z, y, x 축 기준으로 [-3, 1] x [-40, 40] x [0, 70.4] meter 범위 내의 point cloud를 고려하였고 T = 35를 기준으로 sampling 한다구 합니다. Pedestrain과 Cyclist detection에서는 [-3, 1] x [-20, 20] x [0, 480 meter을 기준으로 point cloud를 수집하였고 T = 45로 설정하였습니다. random sampling 하는 기준은 T만 존재하는 것은 맞지만 애초에 data로 다루는 범위가 다르기에 detection하는 object에 따라 다르게 기준을 선정하여 데이터를 수집하고 있는 것 같습니다

  3. 안녕하세요. 좋은 리뷰 감사합니다.

    3D에 관해서는 잘 모르지만 point cloud는 sparsity가 높아 실제 데이터를 보면 빈 voxel의 비율이 매우 높은 것으로 알고 있습니다. 또한 수집되는 환경에 따라 어떤 voxel은 dense한 경우가 있을 수도 있을 텐데요, 그렇다면 random sampling 시 max point 개수인 T를 정하는 일반적인 기준이 있을까요?

    1. 안녕하세요 ! 댓글 감사합니다.

      네 말씀하신대로 수집한 point cloud를 voxel 형태로 변형시킬 경우 본문에서도 이야기한 것 처럼 point가 존재하는 voxel은 전체 voxel에 10%에 불과하게 됩니다. 다만 max point 개수인 T라는 것이 본래 어떤 기준을 가지고 설정되는지까진 알 수 없지만 .. 논문에서 저자들은 detection할 object에 따라 유동적으로 T를 변경하면서 설정하는 것으로 보아 임의로 설정할 수 있는 것이 아닐까 싶습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다