[Flownet 2.0] Pytorch에서 Optical Flow 추출하기

Introduction

현재 차기 영상대조 과제를 진행하면서 가장 먼저 구현 목표로 삼은 것은 항공영상에서 진행 방향의 Dominant한 속력을 추출해내는 것이다. Classic Computer Vision에서는 각 Keyframe에서 Feature를 추출하여 RANSAC과 필터를 이용하여 속도를 추정하는 방식을 사용했으나 현재 트렌드는 딥러닝을 이용하여 원하는 정보를 추출해내는 방식을 사용하고 있다. 따라서 차기 과제에서는 기존 방법과 더불어 새로운 딥러닝 테크닉을 활용하는 것이 필수적일 것이다. 이번 세미나에서는 항공영상에서 Optical flow를 추정하여 진행방향 속력을 구하는 예제를 Docker 위에서 구현하는 방법을 소개한다.

Docker

Docker 란?

Docker가 필요한 이유

기존의 개발환경 관리 또는 파이썬 패키지 관리 툴을 사용하더라도 Local을 깨끗하게 유지하기 어렵다. 다시 말해 Open-source 라이브러리를 사용하거나 Linux 환경에서 개발이 필요할 때 빈번하게 발생하는 의존성 문제를 해결하는 데는 2020년 1월 현재 가장 인기있는 개발 도구이다. Anaconda나 virtualenv와 유사하지만 VMware나 VirtualBox처럼 OS-level 가상화를 지원한다는 차이점이 있다.

Docker의 장점

  • 기존 가상화 솔루션과의 차이점

  • 기존 가상화 솔루션은 대부분 GUI를 제공하며 Hardware 레벨에서의 가상화까지고 지원하기 때문에 host의 리소스를 거의 대부분 사용할 수 있다는 장점이 있다. 그렇기 때문에 사용하기에 무겁고, 실제 OS를 설치하는 것과 동일한 프로세스를 거치기 때문에 한 번 세팅하는 데 상당한 시간이 소요된다.

  • Docker는 가상환경을 Container라고 부르며 새로운 환경의 빠른 설정이 가능하지만 퍼포먼스는 VM에 비해서 낮기 때문에 실제 코드를 실행하기보다는 개발용으로 많이 쓰인다.

내 컴퓨터에 Docker를 설치하자

들어가기 전에

현재 Docker는 Windows에서 GPU를 지원하지 않는다. 딥러닝 프레임워크 대부분이 GPU를 사용하는 것을 전제로 하고 있기 때문에 외부망 PC에서 Docker로 코드를 테스트해보는데는 한계가 있다. OS는 Ubuntu 18.04에서 테스트한다. Docker에서 GPU 가속을 사용하려면 NVIDIA 그래픽카드에서 네이티브로 동작하는 Nvidia-docker를 설치해야 한다. Docker 19.03 이후 버전에서는 GPU를 네이티브로 지원하지만 아직 불안정하다.

NVIDIA driver

먼저 드라이버 버전(숫자 3자리) 확인 후 설치. 그래픽카드마다 지원하는 드라이버 버전이 다를 수 있으므로 반드시 확인해야 한다.

ubuntu-drivers devices # check suitable driver version

# Add repository and install driver
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
sudo apt-get install nvidia-driver-000
sudo reboot

# Check if driver is appropriately installed
nvidia-smi

Docker

  • GPU가속이 필요 없다면 이 부분만 실행해도 된다.
  • https://docker.com 에 가입한 후 Docker CE와 CLI 다운로드 링크
# Allow apt to use repo over HTTPS
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

# Add Docker's official GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Verify now we have fingerfint
$ sudo apt-key fingerprint 0EBFCD88

pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

# Add official Docker repository
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

# Update apt index and install
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

# Last verification
$ sudo docker run hello-world

Nvidia-docker

# Add the package repositories
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

$ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
$ sudo systemctl restart docker
  • (★★★) Host에서 Cuda toolkit은 설치하지 않아도 됨! 이것만으로도 딥러닝 프레임워크 세팅이 굉장히 간편해졌다.

Linux postinstallation

리눅스에서는 docker에게 슈퍼유저 권한을 주기 위해 아래와 같은 절차가 필요하다.

sudo groupadd docker
sudo usermod -aG docker $USER

# Logout and login for re-evaluation of membership
newgrp docker

# Verify if we can run docker without sudo
docker run hello-world

만일 config.json에 접근할 수 없다는 에러가 발생하면 도커 디렉터리에 권한을 추가해준다.

sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R

기본적인 Docker 사용법

Dockerhub

  • Docker Image repository : github가 소스코드를 저장하고 공유하는 곳이라면, dockerhub는 docker image를 저장하고 공유함
  • pyTorchtensorflow와 같은 딥러닝 프레임워크를 바로 실행할 수 있도록 업로드 된 경우가 많다 : Jupyter + Tensorflow + Pytorch...
docker pull tensorflow/tensorflow-gpu:latest

Docker CLI (Command Line Interface)

  • Docker는 GUI가 별도로 존재하지 않고 프롬프트 상에서 인터프리터 형식으로 작동한다.

  • Basic commands

    • command
      pull Repository에서 이미지를 로컬로 가져온다.
      push 로컬의 이미지를 Repository로 내보낸다.
      run 이미지를 컨테이너로 실행한다.
      stop 실행중인 컨테이너를 정지시킨다.
      start 정지된 컨테이너를 재실행한다.
      rm 정지된 컨테이너를 삭제한다.
      ps 실행중인 컨테이너들의 상태를 출력한다.
      attach 실행중인 컨테이너로 접속한다.
      commit 컨테이너의 변경사항을 이미지로 커밋한다.
      images 로컬에 저장된 이미지들의 목록을 출력한다.

소결론

Docker ?

  • 장점
    • '환경'을 정말 쉽고 빠르게 구축할 수 있다는 점
    • 프레임워크 공식 이미지가 있기 때문에 OS나 VM에 직접 설치할 필요가 없음
    • 환경이 전혀 다른 개발자들 사이에서도 dockerfile만 공유하면 완벽히 동일한 환경에서 소스코드 실행 가능
  • 단점
    • VM에 비해서 낮은 퍼포먼스(Sandbox의 단점)
    • Windows에서 GPU 사용 불가
    • CLI에 익숙해져야 함

최근 가장 핫한 개발환경으로 누구나 쉽게 가상환경을 구축하고 공유할 수 있기 때문에 최신 트렌드를 따라가려면 반드시 알아두어야 하는 툴이다. 그러나 자신이 개발하고자 하는 타겟에 적합하지 않을 수 있다. 정답은 없다.

Flownet2.0

NVIDIA에서 optical flow 추정을 위해 개발하였다. github에는 해당 논문과 함께 pytorch 버전이 올라와있다.

flownet2.0을 Docker에서 Pull 해보기

Dependencies

원래대로라면 Host OS에 직접 설치하든, VM이나 가상환경에 설치하든 일일이 Dependency를 설정해 주어야 한다. flownet2.0pytorch, numpy, PyTorch, scipy, scikit-image, tensorboardX, colorama, tqdm, setproctitle을 모두 pip을 통해서 설치해 주어야 한다. 하지만 Docker에서는 명령어 한 줄로 모든 설정 끝!

Dockerfile이란?

C언어를 사용할 때의 MakeCMake를 생각하면 이해가 빠르다. 소스코드를 컴파일하고 링크하는 작업을 위해서는 C언어 소스코드에서 헤더와 라이브러리 의존성을 일일이 맞추어 주어야 하는 불편함이 있다. 이 작업을 쉽게 해주는 툴이 바로 Make이다. dockerfile도 마찬가지로 이미지를 빌드하는 데 필요한 환경을 미리 명시해두고 docker가 알아서 의존성을 구성하도록 한다. 의존성에는 OS 종류와 버전, 파이썬 라이브러리, 기타 등등.. 모든 필요한 것을 단 몇줄로 설정할 수 있다.

Build Docker Image from dockerfile

docker는 Local path나 URL에서 바로 빌드를 지원한다. github의 URL을 이용하여 빌드한다.

docker build github.com/NVIDIA/flownet2-pytorch

저장소에 dockerfile이 있기 때문에 해당 파일을 참조하여 알아서 환경이 설정된다. 로컬에 설치된 것은 NVIDIA 드라이버와 docker 뿐이다. 다음으로 해당 코드에서 제공하는 network를 빌드한다.

# get flownet2-pytorch source
git clone https://github.com/NVIDIA/flownet2-pytorch.git
cd flownet2-pytorch

# install custom layers
bash install.sh

예제

기본 예제 실행

docker run --gpu all -it --shm-size=1024m NVIDIA/flownet2-pytorch:latest

python main.py --inference --model FlowNet2 --save_flow --inference_dataset MpiSintelClean \
--inference_dataset_root /path/to/mpi-sintel/clean/dataset \

항공사진 트레이닝

Parrot Group의 커뮤니티인 SenseFly에서 제공하는 데이터셋을 이용했다. 스위스 루체른 지역의 3D Mapping을 위한 데이터셋으로 직선 이동 구간 영상을 추출하여 Optical flow를 추정한다. 해당 영상의 촬영 고도는 162m이다.

python main.py --inference --model FlowNet2 --save_flow --inference_dataset ImageFromFolder \
--inference_dataset_root /path/to/dataset \

결과 도시하기

flowiz 라이브러리를 사용하면 .flo파일을 jpgmp4로 간편하게 변환이 가능하다 :

pip install flowiz -U
python -m flowiz flodir/*.flo -o flodir/png/

이번 세미나에서 사용된 장비의 RTX2000번대 GPU는 CUDA10.0 이상만을 지원한다. flownet2.0의 의존성이 CUDA9.0인 문제가 있어 제대로 된 실행 결과를 얻을 수 없는 문제가 있다.

결론

Docker를 이용하여 개발에 필요한 가상환경 셋업 방법에 대해 알아보았다. 강력한 가상환경 구축 기능으로 간편하게 원하는 의존성을 이용하여 개발이 가능하다. 또한 공식 이미지가 있기 때문에 설치에 필요한 시행착오를 크게 줄일 수 있는 장점이 있다.

예제로서 MPI-Sintel 예제와 SensFly 항공사진을 이용한 트레이닝을 실행하려 했지만 RTX2000번대 GPU의 CUDA 문제로 실행이 어려웠다. 차후에 해당 라이브러리를 업데이트하여 다시 학습시키는 것이 필요할 것으로 생각된다.