이전에 Super-Resolution Imaging 관련으로 관심을 가졌다가, 오래전에 공개 되었던 한 홍콩의 대학쪽에서 공개된 논문과 소스코드를 이번에 손을 보게 되었습니다.

http://mmlab.ie.cuhk.edu.hk/projects/SRCNN.html

 이전에 fl_imgtk 에 Lanczos3 까지 초 고속으로 구현을 해 보았던지라, 이번 Super-Resolution (이하 SR) 은 어렵지 않게 구현을 할 수 있을 거로 추측을 해 봤습니다만, 결론적으로 대단히 쉽지 않은 부분이 많았습니다. 특히 지속적으로 32 에서 64번씩 반복되는 커널 매트릭스 구조는 도저히 속도를 개선 하는데 쉽지 않은 부분이었습니다만, 그럼에도 만들어진 영상의 품질은 아마 현존하는 이미지 리사이즈 알고리즘 중에서는 최고봉이 아닐까 합니다.

오른쪽이 원래 작은 이미지, 왼쪽이 SR 결과

 아무래도 Lanczos3 와 같은 리사이즈 엔진은 인간의 눈으로 볼떄 최상의 결과를 불러 오기 위해 영상이 크게 변하는 부분이 많은 왜곡이 들어가게 됩니다만, 이 SR 은 작은 영상이미지가 가지는 미세한 변화에 대한 신호를 최대한 살려서 목적 크기에 맞게 이를 복구 하게 됩니다.

 그래서 품질에 있어서는 일반적으로 알려진 현존 이미지 처리 중엔 가장 괜찮은 품질을 나타 내 줍니다만, 반면 속도가 경악스러운 속도를 보여 주는데, 이런 느린 속도의 주범은 아무래도 이런 알고리즘들이 대부분 Matlab 으로 만들어 졌거나, OpenCV 등으로 구현이 되어 있다는 것 입니다.

 그마나 위에 공개된 오픈소스직접 fork 하여 OpenMP 를 적용 해 거의 새로 만들어 바 그나마 CPU 를 모두 활용할수 있게 되었습니다만 ... 256x256 크기를 가지는 RGB 이미지를 2배 ( 면적은 4배 ) 인 512x512 로 만드는데 걸리는 시간은 제가 쓰는 노트북 i6-7200U 기준으로 무려 65초 가량이 걸렸습니다. 게다가 이게 OpenMP 가 없을 경우 최대 2배까지 느려 진다는 것 입니다.

 결론은 이것이 OpenCV 의 구조에서 부터 비롯되는 여러 복합적인 문제임을 직관하여, 이를 바로 OpenCV 없이 구동 할 수 있는 구조로 새로 만들어 내었습니다. 이때 OpenCV 에서 구현 되어 있던 것들 대부분을 모두 새로 구현 하게 되었고, 다양한 테스트를 통해 이런 부분을 모두 100% 만들어 내어 다음 두 위치에 소스가 올라가게 되었습니다.

 위의 소스들은 모두 github 에 공개 되어 있으며, 각기 GPLv2 와, LGPLv3 로 라이센스가 적용 되어 있어서 상용으로 사용하기엔 조금 곤란할 수 있습니다만, 제가 따로 만든 libsrcnn 은 그나마 LGPLv3 를 지정해 놨습니다. ( 원래 코드를 만든 분이 GPLv2 를 지정 해 두어 제한 적 입니다 )

256x256 RGB 이미지를 2배로 키우는데 걸리는 성능

은 모두 CPU 성능에 제한적 입니다만, 다음 정도로 측정 해 보았습니다.
먼저 제가 쓰는 노트북 i5-7700U 에서는 다음과 같은 측정이 되었습니다. 각기 OpenCV Static build 로 구동 된 것과, libsrcnn 으로 구동되는 테스트 프로그램으로, 둘 다 같은 이미지를 같은 크기로 만들어 내는데 걸리는 시간 입니다. i5-7700U 는 CPU core 2개에 hyper-thread 로 실제 4개의 thread 를 가지는 제품이나, 성능은 데스크탑 i3 급 입니다.

  기본으로 OpenCV + OpenMP 로 60초가 넘는 시간동안 구동 되던 속도가, OpenCV 없이 OpenMP 로 최적화 해서 구동을 하면 거의 1/3 의 속도로 처리가 가능 합니다.

 여기에 좀 더 빠른 i7-7 씨리즈의 8 개 thread 를 가진 시스템에서 구동을 해 본 결과는 ...

34초에서 11초로 줄어든 것으로 약 동일하게 3배 정도 빠르게 구동 됩니다만, 아무래도 노트북 CPU 에 U가 붙은 저전력 CPU 로는 빡센 작업이 업렵다는걸 다시 배웁니다.

 그런데 여기서 더욱 더 놀라운 점 하나는 이 소스를 Embedded Linux 를 올린 AARCH64 에서 구동했을떄는 어떨까? 입니다. 그래서 직접 해 본 결과:

nVidia Jetson TX2 에서 CPU 6개의 core 중, 2개는 FPGA 로 돌려 쓰고 있어서 BIG 4 core 만으로 구동한 상태에서 ARM AARCH64 가 가지는 이점과 nVidia 의 전류소모를 무시한 오직 CPU 빨 연산능력은 ... i7-7 씨리즈 보다 빠릅니다!

 OpenCV 를 static 으로, OpenMP 를 지원 하도록 동일하게 빌드 하여 테스트 했는데 그냥 19초만에 연산을 종료 하였으며, 여기에 libsrcnn 으로 만든건 4.6초가 걸립니다. 게다가 이 차이는 거의 4배의 차이 ! 아무래도 ARM architecure 로 라이브러리를 많이 만들어 온 경험이 있다고 자부함에도 이정도 성능 차이가 날지는 몰랐습니다.


 아직은 초기버젼이라 어디에 버그가 남아 있을지도 모르지만, OpenCV에 염증을 느껴서 직접 만든 소스를 사용해 보실 분들은 위에 소개된 github 를 이용해 주시되, 직접 사용을 해 보기 위해서는 다음과 같은 능력이 필요 합니다.

  • Makefile
  • G++
  • OpenMP ( MacOSX 에서는 -fopenmp 를 지우시고 빌드 해야 합니다. )

라이센스 경고

 본 소스코드는 LGPLv3 를 조건으로 공개 된 오픈 소스 입니다. 게다가 원작자는 GPLv2 ( LGPL 로 변경 했다고 하는데, 정작 소스 내에 LICENSE 는 GPLv2 임 ) 제한이 있으므로, 상업적 목적으로 사용하실 경우 C++ 로 해당 코드를 사용하는 부분은 소스코드를 공개하시는 것을 잊지 말으셔야 합니다.


M$VC 미지원

 본 소스코드는 M$VC 에서는 기본적으로 OpenMP 와 함께 빌드가 불가능 합니다. 제 소스를 fork 하셔서 새로운 소스로 만들어서 concurrency 나 타 병렬처리로 수정하셔서 사용하시기 바랍니다.

Posted by 견족자K rageworx