반응형

개요

OpenCV 에서는 오래전부터 nVidia CUDA를 사용할 수 있도록 해줬다. 그중 DNN 모듈은 기존 딥러닝 플랫폼인 텐서플로나 파이토치 같은 모델을 변형하여 사용할 수 있다.

이때 cuDNN을 통해서 그래픽 카드를 활용하면 기존 cpu를 사용한 것 보다 좀 더 빠른 연산을 수행할 수 있다. 이 과정은 일반적은 OpenCV 빌드보다 신경써줘야 할 것이 많다.

서버 환경이 아닌 소형 임베디드 환경을 전제로 하여 이글을 작성하는 시점에 가장 널리 사용중인 Ubuntu 20.04 desktop기준 개발환경으로 서술한다.

만약 nVidia의 jetson 시리즈 보드를 사용할 경우 기본적으로 openCV가 빌드되어 있다.

기존 OpenCV 삭제

기본적으로 python3 pip를 통해서도 openCV 라이브러리가 설치 되어 있기도 하다. ros를 설치 했을 경우에도 기본적으로 opencv가 함께 설치 된다. 그리고 이미 설치가 되어 있더라도 cuDNN가 지원이 되지 않다면 이 또한 새로 빌드를 해야 한다.

# 기존 opencv 4.x 설치 확인
pkg-config --modversion opencv4

# 기존 opencv 3.x 이하 설치 확인
pkg-config --modversion opencv

# uninstall opencv-python
pip3 uninstall opencv-python

# ros를 통해서 설치가 되어 있는 경우
sudo apt purge ros-*
sudo apt autoremove

# 과거에 source code를 직접 빌드해서 설치했었을 경우
sudo find /usr/local -name "*opencv*" -exec rm -i {} \;

위의 명령어를 순서대로 해도 상관이 없지만, 먼저 확인을 하고 순차적으로 진행하는 것을 권장한다.

그래픽 드라이버 설치

그래픽 드라이버 설치를 할 경우 ubuntu desktop일 경우 super 키로 검색하여 "addtional drivers" 창에서 설정을 해도 상관은 없다. 다만 설치를 할경우 meta 라고 표기 되어 있는 것을 설치해야 모니터 외에 연산을 용도로 그래픽 카드를 사용할 수 있다.

# 일반적인 desktop 환경의 경우
sudo apt update
sudo apt install cuda-dirvers

# desktop이 아닌 다른 장치의 경우
sudo lspci -v | less
sudo ubuntu-drivers devices

# 해당 경우는 rtx3090 경우 저장소 추가하여 설치하는 예시
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
sudo apt-get install nvidia-driver-460

# 설치를 완료한 뒤에는 reboot 할 것
reboot

정상적으로 설치가 되었을 경우 아래의 명령어를 실행했을 때 그래픽 카드에 대한 정보가 출력이 되어야 한다. 만약 출력이 되지 않는다면, 제대로 그래픽 카드 드라이버가 설치 되지 않은 것이다.

nvidia-smi

그래픽 카드 정보를 보면 CUDA 다음 버전이 있는데, CUDA 버전을 의미하는 것이 아니라 사용 가능한 버전을 표시되는 것이다.

CUDA 설치

nVidia 웹에서 CUDA를 설치하려고 하면 최신 CUDA로 다운로드 받도록 유도하는데 최신 버전의 경우 안정화 지원이 덜되는 경우가 많기 때문에 가능하면 최신화 이전 버전을 설치하는 것이 좋다. 아래 링크에 접속하여 CUDA 버전을 고르고 OS 등에 맞춰서 local로 설치를 하려고 하면, 터미널에 입력하는 명령어가 표시된다 이를 따라서 진행하면 된다.

https://developer.nvidia.com/cuda-toolkit-archive

 

CUDA Toolkit Archive

Previous releases of the CUDA Toolkit, GPU Computing SDK, documentation and developer drivers can be found using the links below. Please select the release you want from the list below, and be sure to check www.nvidia.com/drivers for more recent production

developer.nvidia.com

cuDNN 설치

cuDNN은 딥러닝같은 연산을 최적화 시켜주는 라이브러리다. 시간이 지나면, 설치 패키지로 배포가 되겠지만, 아직은 직접 다운로드 받아서 복사를 해줘야 한다(복사가 설치다). 앞에 설치한 CUDA 버전에 맞춰서 다운로드 받아으면 된다.

https://developer.nvidia.com/rdp/cudnn-archive

 

cuDNN Archive

Download releases from the GPU-accelerated primitive library for deep neural networks.

developer.nvidia.com

압축 파일을 다운로드가 완료가 되었다면 압축을 해제하고 각 필요한 파일들을 맞는 위치에 복사를 한뒤에 권한을 설정해주면 된다. 이때 앞의 CUDA 버전에 맞춰서 맞는 폴더로 복사를 하면 된다. 아래 예시는 cuda-11.8 을 설치했을 경우이다.

tar -xvf cudnn-linux-x86_64-8.8.1.3_cuda11-archive.tar.xz
cd cudnn-linux-x86_64-8.8.1.3_cuda11-archive
sudo cp include/cudnn*.h /usr/local/cuda-11.8/include
sudo cp -P lib/libcudnn* /usr/local/cuda-11.8/lib64
sudo chmod a+r /usr/local/cuda-11.8/include/cudnn*.h /usr/local/cuda-11.8/lib64/libcudnn*

update-alternatives

gcc 같은 빌드 툴들이 여러버전이 설치 되었을 경우 디폴트로 실행하도록 할 필요가 있다. 이 경우 전통적으로 심볼 링크를 사용하는데, 이를 관리해주는 update-alternatives 를 활용하면 억지로 심볼링크를 쓸 필요가 없다. 아래의 예제는 cuda-11.8 일 경우를 전제로 작성한다.

# update-alternatives config 확인
sudo update-alternatives --config cuda

# 아무것도 없는 경우
sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.8 11

# update-alternatives config 재확인
sudo update-alternatives --config cuda
# 추가된 항목이 보이게 됨

전통적인 심볼링크

위의 update-alternatives 가 없거나 자신이 상남자라고 생각한다면 전통적인 방식으로 직접 심볼링크로 해도 상관은 없다.

# 기존 심볼링크 제거
sudo rm /usr/local/cuda
# 새 심볼링크 생성
sudo ln -s /usr/local/cuda-11.8 /usr/local/cuda

nvcc 확인

터미널에서 nvcc가 정상적으로 작동되는지 확인한다. 표시되는 정보에 설치된 CUDA와 같은 버전이 표시되어야 한다. 만약 nvcc가 실행되지 않는다면 환경변수를 아래와 같이 설정해준다. 그리고 이 터미널에서 opencv를 빌드해야 한다.

# nvcc 정보 확인
nvcc -V

# nvcc -V 정보가 안보일 경우
export PATH=$PATH:/usr/local/cuda/bin
export CUDADIR=/usr/local/cuda
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64

컴파일러 변경

opencv4.x 빌드시 gcc/g++ 버전이 너무 높으면 빌드가 되지 않는다. Ubuntu 20.04 LTS desktop 에 기본적으로  gcc-9 버전이 설치되어 있다. 이 경우 빌드를 시도하면 gcc-8, g++-8 이상은 빌드할 수 없다는 에러메시지를 볼 수 있다. 따라서 gcc-7, g++-7을 설치하자.

sudo apt install -y gcc-7 g++-7

이렇게 설치한 뒤에도 여전히 gcc-9와 g++-9가 default로 되어 있기 때문에 update-alternatives를 이용해서 바꿔주자

# 변경 및 우선순위 확인
sudo update-alternatives --config gcc
sudo update-alternatives --config g++

# 누락 되었을 경우
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 7
sudo update-alternatives --instlal /usr/bin/g++ g++ /usr/bin/g++-7 7

역시 update-alternatives가 없거나(없으면 설치하면 됨), 자신이 상남자라면 직접 심볼링크를 생성해서 사용해도 상관 없다. 물론 평범한 겁쟁이라면 아래 방법은 가능하면 피하자.

sudo rm /usr/bin/gcc /usr/bin/g++ /usr/bin/cc /usr/bin/c++
sudo ln -s /usr/bin/gcc-7 /usr/bin/gcc
sudo ln -s /usr/bin/g++-7 /usr/bin/g++
sudo ln -s /usr/bin/gcc-7 /usr/bin/cc
sudo ln -s /usr/bin/g++-7 /usr/bin/c++

# 버전확인
gcc --version

gcc 와 g++ 버전이 7로 보인다면 이제 다음단계로 넘어가면 된다.

VTK 설치

OpentCV가 viz 부분을 VTK 모듈을 의존한다. 만약 사용하지 않는다면 OpenCV 빌드시 해당 부분을 off 하고 빌드를 해도 된다.

sudo apt install vtk7

GTK 2.0 이상 설치

OpenCV가 리눅스에서 imshow() (image show) 같은 독자적인 창을 생성할 경우 사용하는 의존 모듈이다. 만약 개발중이 아니거나 중간중간 로컬에서 이미지를 표시하지 않는다면, OpenCV를 빌드할때 해당 옵션들을 off 한 상태에서 빌드하면 된다. 버전은 최소 2.0 이상이 필요하다.

일반적인 개발환경이라면, 해당 모듈도 미리 설치를 해주자.

sudo apt install -y libgtk2.0-dev

OpenCV 빌드

다운로드

이제 OpenCV 소스코드를 다운로드 받을 차례이다. OpenCV 본가 외에 contrib 모듈이 존재하는데 해당 모듈은 beta 수준의 모듈들을 담고 있다. 충분한 시간이 지나면 OpenCV 본 소스에 편입이 되지만, 최신 기능을 사용하기 위해서는 contrib가 필수 적이다.

둘다 버전에 맞춰서 다운로드를 받아야 한다. 예시에서는 4.6.0 버전으로 받는데 url 체계는 같으므로 존재하는 버전이면 숫자만 바꿔서 wget으로 다운로드 받아도 된다.

cd ~
wget -O opencv-4.6.0.zip https://github.com/opencv/opencv/archive/4.6.0.zip
wget -O opencv-contrib-4.6.0.zip https://github.com/opencv/opencv_contrib/archive/4.6.0.zip
unzip opencv-4.6.0.zip
unzip opencv-contrib-4.6.0.zip

압축을 풀는 과정에서 opencv-contrib-4.6.0.zip 이 생성하는 폴더이름이 opencv_contrib-4.6.0로 바뀌는 경우 있으니 주의 하자.

CMake-gui

대부분 CMake로 makefile을 생성할 경우 스크립트를 만들어서 사용을 한다. 하지만, 직관적으로 어떤 옵션을 빼고 넣어야 하는지 확인하기 어렵기 때문에 여기서는 CMake-gui 를 사용한다. 우선 CMake-gui를 설치하도록 하자.

sudo apt install -y cmake cmake-gui

cmake-gui 를 실행하기 전에 소스파일 폴더 안에 build 폴더를 먼저 만든다. 여기서는 opencv 4.6.0을 다운로드 받아서 진행하는 것을 전제로 한다.

cd ~/opencv-4.6.0
mkdir build

이 터미널은 아직 닫으면 안된다.

super키(윈도키) 를 누른뒤 cmake-gui 를 실행한다. 처음 cmake-gui 를 실행한다면 공란으로 보이는데 우선 where is the source code 경로를 ~/opencv-4.6.0 으로 직접 입력하거나 Browse source 버튼으로 위치를 찾아도 된다. 경로는 가능하면 절대경로로 작성하는 것이 좋다.

where to build the binaries 항목은 아까 만든 ~/opencv-4.6.0/build 경로로 잡는다. 이후에 하단의 configure 버튼을 클릭하면, cmakelist.txt를 찾으면서 초기 설정들을 찾아서 표시해준다.

이제 옵션을 수정하면 된다. JAVA로 개발하지 않는다면, search에 java를 입력해서 해당되는 체크표시를 해제하면 된다. 우리가 지금 빌드하는 목적은 그래픽 카드를 이용해서 opencv DNN 모듈을 사용하려는 거니 다음 항목들을 체크한다.

  • WITH_CUDA
  • BUILD_CUDA_STUBS
  • OPENCV_DNN_CUDA

이외에 유료 모듈과 pkg-config 를 설치 되게 위해서 아래 항목들도 체크 표시를 해준다.

  • OPENCV_ENABLE_NONFREE
  • OPENCV_GENERATE_PKGCONFIG

그리고 시행착오로 에러메시지를 통해 삽질(?)로 알게된 옵션을 추가한다. 옵션을 추가하는 방법은 add entry 를 통해서 추가하면 된다.

옵션라벨 타입
CUDNN_INCLUDE_DIR PATH /usr/local/cuda/include
CUDNN_LIBRARY PATHFILE /usr/local/cuda/lib64/libcudnn.so
CUDNN_VERSION STRING 8.8
OPENCV_EXTRA_MODULES_PATH PATH ~/opencv_contrib-4.6.0/modules

opencv-python 모듈처럼 하나의 통합된 형태의 라이브러리를 사용하는 것이 아니면, BUILD_opencv_world 항목도 찾아서 체크를 해제하면 된다.

모든 설정을 마쳤으면 configure 버튼을 다시 클릭한다. 설정을 적용하는 과정에서 필요한 파일을 다운로드 받기도 한다. 아무런 에러가 없이 무사히 완료가 되었다면, generate 버튼을 클릭하여 빌드 파일을 생성한다. 여기까지 무사히 마쳤다면 cmake-gui 창은 닫아도 된다.

make & install

이제 다시 터미널에서 생성된 파일들이 있는 build 폴더로 이동한다. make를 입력하여 빌드를 시작하면 된다. 만약 빌드 시간을 측정하고 싶다면 time make 처럼 입력해도 된다. 컴퓨터 성능에 따라서 걸리는 시간의 차이가 있다.

cd ~/opencv-4.6.0/build
# 큰무리가 없다면
make

# 만약 빌드 환경의 메모리가 부족하다면 $(nproc) 보다 작은 숫자
make -j $(nproc)

만약 메모리가 부족할 것 같다면, -j 옵션으로 job(사실상 thread) 수를 줄여서 빌드하면 된다. 대신 시간이 더 걸린다.

무사히 빌드를 마쳤다면 이제 라이브러리 설치를 하면 된다.

sudo make install

정상적으로 마친뒤에 설치 여부를 확인한다.

pkg-config --modversion opencv4

opencv 버전이 표시가 된다면 정상적으로 설치가 된 것이다. pkg-config 는 c++ 코드를 빌드할때 필요한 존재니 반드시 있어야 한다.

참조

 

 

OpenCV + CUDA 직접 빌드하기 (Windows/Linux 종합)

최근에 opencv에 있는 dnn을 한번 써보려고 직접 소스를 받아서 빌드(build)해 보았다. 역시나 엄청난 삽질의 연속이고 할 때마다 이것 저것 해결책을 검색하느라 많은 시간을 소모한다 (삽질은 누구

darkpgmr.tistory.com

 

OpenCV Building with CUDA CUDNN - No CUDNN

Hi, It seems that you already find in in this comment: For Jetson 4.5, include path is /usr/include/ and the library path is /usr/lib/aarch64-linux-gnu/. Thanks.

forums.developer.nvidia.com

 

반응형
반응형

CMake 익히기 : 기초문법 (2)

작성 배경

 CMake의 가장 큰 장점은 C/C++ 크로스 플랫폼에 빌드를 할 수 있다. 그러나 임베이디드의 대부분을 차지하는 리눅스 환경의 경우 적당한 빌드 시스템이 CMake만한게 없다는 것도 함정이다. 또한 다른 사람이 만들어 놓은 것을 사용하기는 쉽지만, 막상 규모가 조금 되는 프로그램을 만들려고 하면, 쉽지 않다. 이 때문에 간단하게나마 문법을 조금씩 정리한다.



CMake 기초문법


end가 붙은 키워드의 arg

 end키워드가 붙은 경우(endif, endfunction, endmacro, while, 등)에 앞의 arg를 동일하게 적어 줘서 여러 키워드가 중첩이 될 경우 구분할 수 있는 역할을 할 수 있다. 하지만 붙이지 않아도 된다.



매크로(macro)

 CMake에서 매크로는 문법상 함수와 동일하다. 다만, 동작 방식에서 차이가 있다. 함수의 경우 메모리에 동적으로 생성되어 작동하는 반면 매크로는 C의 매크로처럼 호출 부분에 작성되어 있는 절차를 삽입하는 방식이다.

macro(hello_macro)
    message("hello world")
endmacro(hello_macro)

hello_macro()



조건문(if)

 조건문 if()도 마지막에는 endif()로 끝이 나야 한다. if()조건 외 실행할 경우 else()가 사용된다. if()외에 다른 조건을 정의 할때는 elseif()를 사용한다.


 조건문이 참이 되는 경우는 ON, YES, Y, TRUE, 또는 0이 아닌 값이다. 반면 거짓이 되는 경우는 0, OFF, NO, FALSE, N, IGNORE, ""이다.


 또한 조건문에서 함께 사용되는 비교, 논리 연산자의 경우 기호가 아닌 대문자 키워드로 표현을 한다. 비교 연산자 : EQUAL, LESS, GREATER

논리 연산자 : AND, OR, NOT

기타 매칭 :  MATCHES [REGEX]

set(VAL 1)

if(${VAL})
    message("${VAL} is TRUE")
else()
    message("${VAL} is FALSE")
endif()



include()

 확장자가 cmake로 작성된 다른 cmake 파일을 포함시킬 수가 있다. C/C++의 include와 유사하다. 다만, 표준라이브러리가 없어서 로컬에서 포함을 해야 한다. 대부분 오픈소스에는 cmake라는 폴더에 .cmake 파일을 모아 놓는다.

 include하게 되면, include된 파일에 있는 매크로나 함수, 변수를 사용할 수 있다.




연습예제

 앞에서 간단하게 살펴본 내용으로 간단하게 실습 예제를 작성해보자. 스크립트를 2개로 만들어서 실행해보자

# cmake폴더의 macro.cmake 파일
macro(check_val_macro val)
    if(${val})
        message("${val} is true")
    else()
        message("${val} is false")
    endif()
endmacro(check_val_macro val)
# 작업 폴더의 CMakeLists.txt 파일
cmake_minimum_required(VERSION 2.6)

include(cmake/macro.cmake)

set(FOO 1)
check_val_macro(FOO)

set(FOO FALSE)
check_val_macro(FOO)


결과는 다음과 같이 나온다





참고자료

OpenCV 소스코드의 CMake스크립트

Mastering CMake A Cross-Platform Build System 서적

반응형

'각종 툴' 카테고리의 다른 글

[PyCharm]기본 키 맵 해제  (0) 2020.12.20
CMake 익히기 : 기초문법 (1)  (0) 2018.02.19
CMake : 공식예제 step1 해보기  (0) 2017.12.11
반응형

CMake 익히기 : 기초문법 (1)

작성 배경

 원래는 공식 웹 페이지에 있는 튜토리얼로 학습을 생각이었는데, 비교적 불친절한 설명과 실습하기에는 부족한 부분이 많았다. 따라서 기존 대형 오픈소스 프로젝트인 OpenCV나 VTK의 CMake 스크립트를 참고하면서 공식 서적인 "Matering CMake-Platform Build System"을 참고하여 조금씩 연습을 하려고 마음을 먹었다.


 "Matering CMake-Platform Build System"서적의 경우 대부분이 레퍼런스이고, 단계적인 설명은 약250페이지 정도 된다.



CMake

 이 글은 CMake를 익히기 위한 내용이기 때문에 CMake의 빌드 메카니즘에 대해서는 과감히 스킵을 한다.


 다만, CMake로 빌드를 하기 위해서는 몇 가지 알아야할 사항이 있다. CMake 자체는 CUI 인터페이스이다. 보니 진입장벽이 존재하고 또한 프로젝트의 규모가 커질 수 록 옵션을 어떻게 잡아야하는지가 막막해진다. 이 때문에 보조 도구가 2가지가 있다. 그리고 공식적으로 대규모의 오픈소스 프로젝트를 빌드할 경우에는 CUI보다는 GUI환경에서 빌드할 것을 권장하고 있다.


CMake-GUI

 기존의 CMake의 기능을 윈도우와 같은 GUI로 사용할 수 있는 툴이다. 리눅스 뿐만 아니라 윈도우, OS X 등에서도 사용이 가능하다. 혹시나 빌드시스템에 대해서 잘 모르지만, C/C++로 만들어진 오픈 소스 프로젝트를 윈도우에서 빌드를 해야할 경우 한번쯤은 사용하게 된다.





CCMake

 CMake-GUI의 경우 OS가 GUI환경을 제공해야 사용이 가능하다는 단점이 있다. 즉, Windows나 Linux의 X-Window와 같은 환경이 먼저 있어야 한다. 하지만, CCMake는 기존의 CUI 환경에서 CMake-GUI와 비슷하게 옵션을 선택할 수 있도록 해준다. 인터페이스는 Vi(혹은 Vim)과 유사한 단축키를 사용한다.





CMake 기초 문법

 정상적으로 CMakeLists.txt가 작동되기 위해서는 서드에 cmake_minimum_required()이 선언되어 있어야 한다. 만약 안하게 될 경우 에러 메시지를 볼 수 있다.



Agruments 구분

 CMake는 CMakeLists.txt에 작성된 스크립트대로 작동이 된다(처음 파일이름 작성시 대소문자 주의). CMake는 대부분 변수와 명령어로 구성되어 있고, 명령어는 command( arg ...) 형태로 구성되어 있다.

 대부분 명령어의 첫 arg는 대부분 특수한 의미가 있다. set()의 경우 첫 arg는 최종적으로 정의되는 변수가 된다.

 명령어의 arguments를 인식하는 것은 다음 예시와 같다.

# set의 예시

# set([변수] [arguements 값])
# set arguments를 2개로 인식
set(VAL "")
set(VAL "a;b;c")
set(VAL "a b c")
set(VAL a;b;c)

# set arguments를 4개로 인식
set(VAL "a" "b" "c")
set(VAL a b c)


 과거에 작성된 문서를 보면, CMake의 명령어들이 대문자로 되어 있지만, vs code의 확장 도구를 통해 CMakeLists.txt를 작성해보면, 명령어는 소문자로 되어 있다. 또한, 변수는 대부분 대문자로 사용하는 관습이 있다(그 이유는 항상 합리적이 이유다).



스코프(Scope) 구분

 C/C++언어에서는 중괄호를 활용해서 함수나 조건문 등의 영역인 스코프를 정의 한다. CMake에서는 이러한 중괄호가 없고 해당되는 command를 호출해서 스코프를 구분한다.


# function의 경우
function(foo)
  message("Hello foo")
endfunction()

# function foo 호출
foo()


 message()의 경우 C의 puts()처럼 입력받은 string을 한줄 출력을 한다. 이러한 명령어는 디버그할때 매우 유용하다. function()은 endfunction()으로 스코프 영역을 정의 해주고, function의 첫 arg는 function의 이름이 된다.



변수

 변수는 set()을 통해서 정의가 되고 ${}를 통해서 값을 호출한다. 또한 변수에 여러개의 값을 정의하면, 배열(혹은 리스트) 형태로 정의가 된다.

 이렇게 정의된 배열은 foreach()로 순차적으로 호출할 수 있다.



연습예제

 이제, 이 페이지에서 배운 내용을 복습해보자.


cmake_minimum_required(VERSION 2.6)

# function foo 정의
function(foo)
  message(${test})
  set(test 2 PARENT_SCOPE)
  message(${test})
endfunction()

set(test 1)
# function foo 호출
foo()

# 값확인
message(${test})

# list item_to_buy
set(item_to_buy apple orange pear beer)

# foreach item_to_buy
foreach(item ${item_to_buy})
  message("Do not forget to buy one ${item}")
endforeach()


 간단하기 때문에 CMakeLists.txt가 있는 폴더에서 다음과 같은 명령어로 빌드한다.


cmake -H. -Bbuild

위의 -B 옵션을 사용할 경우 자동으로 build 폴더를 생성하여 해당 폴더에 빌드를 한다. 빌드 과정에 다음 메시지가 출력되는 것을 확인할 수 있다.





예제에서 특이한 점을 보면, 메시지 결과를 보면, function foo()가 종료되어야 test값이 달라지는 것을 확인 할 수 있다. 이렇게 간단하게 기초 문법을 확인 해봤다.



참고

Matering CMake A Cross-Platform Build System 서적(영문)



반응형

'각종 툴' 카테고리의 다른 글

[PyCharm]기본 키 맵 해제  (0) 2020.12.20
CMake 익히기 : 기초문법 (2)  (0) 2018.02.21
CMake : 공식예제 step1 해보기  (0) 2017.12.11
반응형

라즈비안 : OpenCV를 쉘 스크립트로 설치

배경

 라즈비안에 OpenCV 설치 하는 방법에 대해서는 사실 많은 블로그에서 정리가 되어 있다. 하지만, 그 과정을 따라서 하는 것도 나쁘지는 않지만, 기본적으로 쉘에서 처리가 가능한 것들은 그냥 쉘 스크립트로 만들면 되지 않을까 하는 생각에서 작성하게 되었다.


 이번글은 작성중인 OpenCV 쉘 스크립트를 저장한 정도의 글이 될 것이다. 이후 추후에 쉘 스크립트 문법에 대해서 정리를 해 놓아야 될 것 같다.



OpenCV 설치 확인 및 제거 방법

 라즈비안이 우분투 커널을 사용하므로 마찬가지로 우분투에서 사용했었을 때 실행이 잘 되었다. 다만, 미리 설치가 되어 있을 경우 제거를 해줘야 한다.


pkg-config --modversion opencv
# 제거할 경우
cd {기본opecv 소스폴더의 build 폴더}
make uninstall


제거를 위와 같이 하지 않으면, apt-get purge로 삭제를 해도 pkg-config으로 검사할때 검출이 된다. 아마도 해당 정보를 지우지 못하는 버그가 있는 것 같다.



OpenCV 설치 쉘 스크립트(contirb포함)

 버전 수준으로 따지자면, 0.1 스크립트라고 봐야 할 것이다. 즉, 아직 부족하다고 생각 든다.

 OpenCV3.2.1외에 다른 버전이 필요한 사람이라면, OPENCV_VERSION의 숫자값을 변경하면 된다. 이미 다른 OpenCV가 설치가 되어 있다면, 설치가 진행되지 않는다. 또한, 일반적인 개발 환경으로 셋팅을 한 것이 기 때문에 실제로 배포를 하려고 할 경우는 필요한것만 빌드하도록 수정해야 한다.


#!/bin/bash

# Custom values
OPENCV_VERSION="3.3.1"
OPENCV_REPO=https://github.com/opencv/opencv/archive/"$OPENCV_VERSION".zip
OPENCVCONTRIB_REPO=https://github.com/opencv/opencv_contrib/archive/"$OPENCV_VERSION".zip

# check exit opencv modules
pkg-config --modversion opencv
if [ "$?" -eq 0 ]; then
  echo "You already install opencv"
  exit 0
fi

# Update Debian
sudo apt-get update && sudo apt-get upgrade -y
if [ "$?" -eq 1 ]; then
  echo "Faile Update or Upgrade"
fi

# Install need modules
DEPPKGS=(build-essential cmake)
DEPPKGS+=(pkg-config)
DEPPKGS+=(libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev)
DEPPKGS+=(libavcodec-dev libavformat-dev libswscale-dev libxvidcore-dev libx264-dev libxine2-dev)
DEPPKGS+=(libv4l-dev v4l-utils)
DEPPKGS+=(libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev)
# Qt4
DEPPKGS+=(libqt4-dev)
DEPPKGS+=(mesa-utils libgl1-mesa-dri libqt4-opengl-dev)
# Optimature lib
DEPPKGS+=(libatlas-base-dev gfortran libeigen3-dev)
DEPPKGS+=(python2.7-dev python3-dev python-numpy python3-numpy)

echo "=== Install depend packages ==="
for DEPPKGNAME in ${DEPPKGS[@]}; do
  dpkg -l | grep "$DEPPKGNAME"
  if [ "$?" -eq 1 ]; then
    sudo apt-get install -y "$DEPPKGNAME"
  fi
done
echo "=== End install depend packages ==="

PWD=`pwd`
WORKSPACE="$PWD"/opencv
if [ ! -d "$WORKSPACE" ]; then
  mkdir "$WORKSPACE"
  cd "$WORKSPACE"
fi

OPENCVZIP="$WORKSPACE"/opencv.zip
if [ ! -f "$OPENCVZIP" ]; then
  wget -O "$OPENCVZIP" "$OPENCV_REPO" \
  && unzip -o "$OPENCVZIP" 
  if [ "$?" -eq 1 ]; then
    echo "fail download '$OPENCVZIP'"
    exit 1
  fi
else
  upzip -o "$OPENCVZIP"
  if [ "$?" -eq 1 ]; then
    echo "fail unzip '$OPENCVZIP'"
    exit 1
  fi
fi

CONTRIBZIP="$WORKSPACE"/opencv_contrib.zip
if [ ! -f "$CONTRIBZIP" ]; then
  wget -O "$CONTRIBZIP" "$OPENCVCONTRIB_REPO" \
  && unzip -o "$CONTRIBZIP"
  if [ "$?" -eq 1 ]; then
    echo "fail download opencv_contrib.zip"
    exit 1
  fi
else
  unzip -o "$CONTRIBZIP"
  if [ "$?" -eq 1 ]; then
    echo "fail unzip '$CONTRIBZIP'"
    exit 1
  fi
fi

# OPENCVDIR="$WORKSPACE"/opencv-3.4.0
OPENCVDIR="$WORKSPACE"/opencv-"$OPENCV_VERSION"
if [ -d "$OPENCVDIR" ]; then
  cd "$OPENCVDIR"
else
  echo "does not have dir '$OPENCVDIR'"
  exit 1
fi

BUILDDIR="$OPENCVDIR"/build
if [ ! -d "$BUILDDIR" ]; then
  mkdir "$BUILDDIR" && cd "$BUILDDIR"
else
  cd "$BUILDDIR"
fi


cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D WITH_TBB=OFF \
-D WITH_IPP=OFF \
-D WITH_1394=OFF \
-D BUILD_WITH_DEBUG_INFO=OFF \
-D BUILD_DOCS=OFF \
-D INSTALL_C_EXAMPLES=ON \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D ENABLE_NEON=ON \
-D WITH_QT=ON \
-D WITH_OPENGL=ON \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-"$OPENCV_VERSION"/modules \
-D WITH_V4L=ON  \
-D WITH_FFMPEG=ON \
-D WITH_XINE=ON \
-D BUILD_NEW_PYTHON_SUPPORT=ON \
../

if [ "$?" -eq 1 ]; then
  echo "fail OpenCV cmake build '$PWD'"
  exit 1
fi

time make
if [ "$?" -eq 1 ]; then
  echo "fail OpenCV make"
  exit 1
fi

# only in raspberry
sudo make install
if [ "$?" -eq 1 ]; then
  echo "fail OpenCV install"
  exit 1
fi

echo "complete OpenCV install"
exit 0




후기

 라즈베리 파이3의 경우 듀얼코어(make 옵션의 -j2)까지는 에러가 발생하지 않지만, 마지막부분에서 문제가 있는지, 싱글코어로 빌드한것과 시간차이가 거의 없었다. 코어를 3개를 올릴 경우 빌드 막바지에서 메모리가 부족해서 빌드가 중단되는 문제가 있다.


 일부 후기에서 정정한다. swap 가상 메모리의 크기를 늘리면, 모든 코어를 빌드에 투입하여 시간을 단축 시킬 수 있다. 방법은 추후에 기회가 되면 정리 하도록 하겠다.


참조 자료

블로그 OpenCV3.4 설치




반응형
반응형

CMake : 공식예제 step1 해보기


MS의 VS 시리즈 통합개발환경을 사용하다가 리눅스 같은 유닉스 계열에서 비통합개발환경에서 여러 소스파일을 컴파일을 할 경우 이를 도와주는 도구가 shell, makefile, CMake 등이 있다.

 소스파일이 많아지고 복잡해질 수록 shell 보다는 makefile, makefile보다는 CMake가 비교적 적합하다. 특히 CMake의 경우 윈도우에서도 빌드할 수 있기 때문에, 소스코드 생성시 의 운영체제의 고유 API를 사용하지 않았다면, 동일한 소스파일을 빌드할 수 있다. 이를 이용해서 OpenCV등 오래전 부터 지속된 오픈소스 프로젝트들이 CMake를 사용해서 사용되어져 왔다.


 문제는 이러한 강력한 기능이 있음에도 불구하고 튜토리얼 문서는 관리가 안되고 있는 듯하다. 이 글을 기록하는 시점에 3.5.1버전이 필자의 리눅스에 설치되어 있지만, 공식 홈페이지의 메인 튜토리얼에는 여전히 2.6 버전으로 되어 있다. 게다가 상당히 난잡하게 기록되어 있다. 아마도 이를 통해서 진입장벽을 만들고 싶었던건지 아니면, 기록이 귀찮았던건지는 물어보지 않아서 알 수 없다.


 일단은 예시 들을 진행을 해보면서, 발생되는 문제점을 해결하면서 기록을 하고자 한다.


CMake 개요

 cmake는 CMakeLists.txt 명으로 된 파일을 스크립트로 인식하여 makefile을 생성하여 최종적으로는 makefile(실행은 make)을 사용하여 실행 및 공유파일을 생성한다.




예시 소스코드


// tutorial.cxx

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"

int main(const int argc, const char * argv[])
{
    double inputValue;
    double outputValue;
    if(argc < 2)
    {
        fprintf(stdout, "usage: %s number\n", argv[0]);
        return 1;
    }
    inputValue = atof(argv[1]);
    outputValue = sqrt(inputValue);
    fprintf(stdout, "The square root of %g is %g\n",
        inputValue, outputValue);

    return 0;
}


 확장자가 cxx이지만 헤더파일을 살펴보면 c인것을 알 수 있다. "TutorialConfig.h"은 CMake에서 설정하는 파일로 빌드 직전에 생성된다.



예시 헤더파일


// TutorialConfig.h.in

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@


"@"로 감싼 부분은 CMake 파일에서 후에 정의 된 값이 들어가서 작성하게 된다.



예시 CMakeLists.txt


# CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(Tutorial)
# The version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)

# configure a header file to pass scma of the CMake settings
# to the source code
configure_file(
    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
    "${PROJECT_BINARY_DIR}/Tutorialconfig.h"
)

# add the binary tree to the search path ofr include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")

# add the executedable
add_executable(Tutorial tutorial.cxx)


만약에 여기 까지 진행을 했는데, math.h에 관련된 에러가 발생한다면, 위의 마지막줄 add_executable() 직전에 한줄을 추가 해주자


# add link libraries
LINK_LIBRARIES(m)

주석에 표기 되어 있는대로 라이브러리를 추가 시켜준다. 원래는 cmake가 알아서 추가 시켜줘야 하는데, 간혹 안되는 경우가 있으니 참고 하도록 하자. 위의 한줄은 math.h를 include 했을 때 컴파일 과정중 링크 단계에서 -lm을 하는 것과 같은 효과가 있다.


CMake에서는 콤마(,)가 없다는 것을 주의 해야 한다.

project(Tutorial)은 이름 그대로 프로젝트 이름을 정의해준다.


 set() 키워드는 CMake내에서 변수를 정의 혹은 초기화를 해준다. set(Tutorial_VERSION_MAJOR 1)이라고 하면, Tutorial_VERSION_MAJOR이라는 변수 없다는 생성해서 초기화를 시킨다.


add_executeable(Tutorial tutorial.cxx)는 결과 파일이름이 Tutorial로 되고 여기에 포함되는 소스가 위에 열거가 된다. 예제에서는 하나의 소스파일이지만, 실제로는 여러개의 소스파일이 사용된다.


참조 자료

공식 튜토리얼(영문)

개발자 블로그



반응형

'각종 툴' 카테고리의 다른 글

[PyCharm]기본 키 맵 해제  (0) 2020.12.20
CMake 익히기 : 기초문법 (2)  (0) 2018.02.21
CMake 익히기 : 기초문법 (1)  (0) 2018.02.19

+ Recent posts