라즈베리파이에 OpenCV를 깔았으니 간단한 OpenCV 프로그램을 만들어보겠습니다. 간단한 엣지 검출 예제를 만들어보면서 소스 코드 편집, 빌드, 실행 방법등을 정리해보겠습니다.
일단 저는 소스 코드 편집을 vi 에디터를 사용하는데요, 라즈베리파이에 기본으로 깔리는 vi는 정확하게 vim.tiny 입니다. 그런데 vim.tiny는 syntax coloring을 지원하지 않네요. 그러므로 vim 패키지를 새로 설치했습니다. 명령어는 sudo apt-get install vim입니다.
프로그래밍 테스트를 할 폴더를 하나 만들고, 특히 OpenCV 관련 코딩을 모아놓을 폴더도 하나 만들도록 합니다. 새로 만들 예제 프로그램은 canny라는 이름의 디렉토리에 만들겠습니다.
pi@GoPiGo:~ $mkdir coding && cd coding pi@GoPiGo:~/coding $mkdir opencv && cd opencv pi@GoPiGo:~/coding/opencv $mkdir canny && cd canny pi@GoPiGo:~/coding/opencv/canny $
이 Makefile은 현재 폴더에서 main.cpp 파일을 컴파일하고, OpenCV 라이브러리를 사용하고, 결과 파일 이름은 현재 디렉토리 이름과 동일한 형태로 생성합니다. 즉, 현재 디렉토리 이름이 canny이니까 main.cpp 파일을 빌드해서 canny라는 이름의 실행 파일을 생성합니다. Makefile을 이용해서 빌드를 하려면 터미널 창에서 make라고만 입력하면 됩니다.
순조롭게 canny 실행 파일이 생성이 되었습니다. 이제 ./canny 명령을 입력해서 실행을 하면 아래처럼 2개의 창이 나타나면서 캐니 엣지 검출 결과를 보여줍니다.
참 쉽죠??
그나저나 캐니 엣지 검출기의 실행 속도가 궁금해졌습니다. 그래서 소스 코드에 아래와 같이 캐니 엣지 검출기 실행 시간을 측정해봤습니다.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(void)
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return -1;
}
int64 t1 = getTickCount();
Mat dst;
Canny(src, dst, 50, 150);
int64 t2 = getTickCount();
cout << "It took " << (t2 -t1) * 1000 / getTickFrequency() << " ms." << endl;
imshow("src", src);
imshow("dst", dst);
waitKey(0);
return 0;
}
위에서 getTickCount(), getTickFrequency() 함수를 조합해서 Canny() 함수의 실행 시간을 측정하였고, 그 결과는 아래와 같습니다.
자세히 보면 왼쪽 아래 터미널 창에 "It took 12.5726 ms." 라고 출력이 되어 있는 것을 볼 수 있는데요.. 512x512 크기의 영상에 대해서 12msec 정도 걸린 것이니 그렇게 아주 나쁘지는 않은 것 같습니다. 근데 몇 번을 더 해보니까 12ms 시간대로 나오는 경우는 거의 없네요. 대부분 16~24ms 정도로 측정이 되었습니다.
라즈베리파이에서 OpenCV 3.2를 설치하는 방법을 정리해보겠습니다. 라즈베리파이에 OpenCV를 설치한다는 것은 OpenCV 소스 코드를 직접 빌드하여 헤더 파일을 복사하고 OpenCV 라이브러리를 생성하는 작업을 의미합니다. 과정이 좀 길지만 차근차근 알아보겠습니다.
OpenCV 소스 코드를 빌드하려면 빌드 관련 도구나 필요한 라이브러리 패키지를 라즈베리파이에 미리 설치해두어야 합니다. 예를 들어, 정지 영상 포맷과 관련된 jpeg 라이브러리나 png 라이브러리, 비디오 파일 포맷 또는 스트리밍 관련 라이브러리 같은 것들을 미리 설치해야 정상적으로 빌드됩니다.
[빌드 관련 도구 설치] 실제 빌드 작업에 앞서 OpenCV 빌드에 필요한 패키지를 설치합니다.
[파이썬] OpenCV를 빌드한 후 C/C++ 뿐만 아니라 Python으로도 프로그래밍을 테스트하려고 합니다. 개인적으로는 Python 2.x 버전을 사용하지 않고 Python 3.x 버전만 사용할 것이구요.. 이를 위해서 python3-dev 또는 python3-numpy 패키지가 필요한데, 얘네 둘은 이미 설치가 되어 있을 겁니다. (없으면 설치해야죠.)
pi@RaspberryPi3:~/opencv $ mkdir build && cd build
[cmake 구성] 아래 명령어가 좀 긴데요, 대충 보면 예제 파일들을 생성하고, Python 2.x 말고 Python 3.x를 지원하도록 하는 등의 옵션을 지정합니다. Extra 모듈 소스 코드 위치를 지정하고, OpenCV 소스 코드 위치가 ../opencv-3.2.0/ 임을 명시합니다. 그리고 cmake가 동작하면서 나타나는 출력 메시지를 모두 cmake_messages.txt 파일에 기록합니다.
참고로 cmake_message.txt 파일에 기록된 내용을 아래 [더보기]에 정리해두었습니다.
-- General configuration for OpenCV 3.2.0 ===================================== -- Version control: unknown -- -- Extra modules: -- Location (extra): /home/pi/opencv/opencv_contrib-3.2.0/modules -- Version control (extra): unknown -- -- Platform: -- Timestamp: 2017-04-10T20:06:49Z -- Host: Linux 4.9.30-v7+ armv7l -- CMake: 3.6.2 -- CMake generator: Unix Makefiles -- CMake build tool: /usr/bin/make -- Configuration: RELEASE -- -- C/C++: -- Built as dynamic libs?: YES -- C++ Compiler: /usr/bin/c++ (ver 4.9.2) -- C++ flags (Release): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -mfp16-format=ieee -mfpu=neon -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden -mfpu=neon-fp16 -O3 -DNDEBUG -DNDEBUG -- C++ flags (Debug): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -mfp16-format=ieee -mfpu=neon -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden -mfpu=neon-fp16 -g -O0 -DDEBUG -D_DEBUG -- C Compiler: /usr/bin/cc -- C flags (Release): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wno-narrowing -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -mfp16-format=ieee -mfpu=neon -ffunction-sections -fvisibility=hidden -mfpu=neon-fp16 -O3 -DNDEBUG -DNDEBUG -- C flags (Debug): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wno-narrowing -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -mfp16-format=ieee -mfpu=neon -ffunction-sections -fvisibility=hidden -mfpu=neon-fp16 -g -O0 -DDEBUG -D_DEBUG -- Linker flags (Release): -- Linker flags (Debug): -- ccache: NO -- Precompiled headers: YES -- Extra dependencies: /usr/lib/arm-linux-gnueabihf/libpng.so /usr/lib/arm-linux-gnueabihf/libz.so /usr/lib/arm-linux-gnueabihf/libtiff.so /usr/lib/arm-linux-gnueabihf/libjasper.so /usr/lib/arm-linux-gnueabihf/libjpeg.so gtk-x11-2.0 gdk-x11-2.0 pangocairo-1.0 atk-1.0 cairo gdk_pixbuf-2.0 gio-2.0 pangoft2-1.0 pango-1.0 gobject-2.0 glib-2.0 fontconfig freetype gthread-2.0 gstbase-1.0 gstreamer-1.0 gstvideo-1.0 gstapp-1.0 gstriff-1.0 gstpbutils-1.0 v4l1 v4l2 avcodec avformat avutil swscale avresample dl m pthread rt -- 3rdparty dependencies: libwebp IlmImf libprotobuf tegra_hal -- -- OpenCV modules: -- To be built: core flann imgproc ml photo reg surface_matching video dnn freetype fuzzy imgcodecs shape videoio highgui objdetect plot superres xobjdetect xphoto bgsegm bioinspired dpm face features2d line_descriptor saliency text calib3d ccalib datasets rgbd stereo tracking videostab xfeatures2d ximgproc aruco optflow phase_unwrapping stitching structured_light python3 -- Disabled: world contrib_world -- Disabled by dependency: - -- Unavailable: cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev java python2 ts viz cnn_3dobj cvv hdf matlab sfm -- -- GUI: -- QT: NO -- GTK+ 2.x: YES (ver 2.24.25) -- GThread : YES (ver 2.42.1) -- GtkGlExt: NO -- OpenGL support: NO -- VTK support: NO -- -- Media I/O: -- ZLib: /usr/lib/arm-linux-gnueabihf/libz.so (ver 1.2.8) -- JPEG: /usr/lib/arm-linux-gnueabihf/libjpeg.so (ver ) -- WEBP: build (ver 0.3.1) -- PNG: /usr/lib/arm-linux-gnueabihf/libpng.so (ver 1.2.50) -- TIFF: /usr/lib/arm-linux-gnueabihf/libtiff.so (ver 42 - 4.0.3) -- JPEG 2000: /usr/lib/arm-linux-gnueabihf/libjasper.so (ver 1.900.1) -- OpenEXR: build (ver 1.7.1) -- GDAL: NO -- GDCM: NO -- -- Video I/O: -- DC1394 1.x: NO -- DC1394 2.x: NO -- FFMPEG: YES -- avcodec: YES (ver 56.1.0) -- avformat: YES (ver 56.1.0) -- avutil: YES (ver 54.3.0) -- swscale: YES (ver 3.0.0) -- avresample: YES (ver 2.1.0) -- GStreamer: -- base: YES (ver 1.4.4) -- video: YES (ver 1.4.4) -- app: YES (ver 1.4.4) -- riff: YES (ver 1.4.4) -- pbutils: YES (ver 1.4.4) -- OpenNI: NO -- OpenNI PrimeSensor Modules: NO -- OpenNI2: NO -- PvAPI: NO -- GigEVisionSDK: NO -- Aravis SDK: NO -- UniCap: NO -- UniCap ucil: NO -- V4L/V4L2: Using libv4l1 (ver 1.6.0) / libv4l2 (ver 1.6.0) -- XIMEA: NO -- Xine: NO -- gPhoto2: NO -- -- Parallel framework: pthreads -- -- Other third-party libraries: -- Use IPP: NO -- Use VA: NO -- Use Intel VA-API/OpenCL: NO -- Use Lapack: NO -- Use Eigen: YES (ver 3.2.2) -- Use Cuda: NO -- Use OpenCL: YES -- Use OpenVX: NO -- Use custom HAL: YES (carotene (ver 0.0.1)) -- -- OpenCL: <Dynamic loading of OpenCL library> -- Include path: /home/pi/opencv/opencv-3.2.0/3rdparty/include/opencl/1.2 -- Use AMDFFT: NO -- Use AMDBLAS: NO -- -- Python 2: -- Interpreter: /usr/bin/python2.7 (ver 2.7.9) -- -- Python 3: -- Interpreter: /usr/bin/python3.4 (ver 3.4.2) -- Libraries: /usr/lib/arm-linux-gnueabihf/libpython3.4m.so (ver 3.4.2) -- numpy: /usr/lib/python3/dist-packages/numpy/core/include (ver 1.8.2) -- packages path: lib/python3.4/dist-packages -- -- Python (for build): /usr/bin/python2.7 -- -- Java: -- ant: NO -- JNI: NO -- Java wrappers: NO -- Java tests: NO -- -- Matlab: Matlab not found or implicitly disabled -- -- Tests and samples: -- Tests: NO -- Performance tests: NO -- C/C++ Examples: YES -- -- Install path: /usr/local -- -- cvconfig.h is in: /home/pi/opencv/build -- ----------------------------------------------------------------- -- -- Configuring done -- Generating done -- Build files have been written to: /home/pi/opencv/build
[빌드!!!] 이제 실제 빌드 작업을 진행합니다. 라즈베리파이3은 4개의 코어가 있지만, -j4 옵션을 주면 발열때문에 문제가 생길까봐 -j2 옵션으로 빌드를 진행합니다. 혹시라도 에러가 발생할까봐 컴파일 메시지는 build_messages.txt 파일에도 저장해둡니다. 빌드 작업은 2시간 넘게 걸렸던 것같고, 간간히 선풍기로 라즈베리파이 보드를 식히면서 진행했습니다.
pi@RaspberryPi3:~/opencv/build/ $ make -j2 2>&1 | tee build_messages.txt
[설치 및 설치 확인] 아래 명령어를 입력한 후 3.2.0 이 출력되면 정상적으로 설치가 된겁니다.
[Python 테스트] python3을 실행하여 OpenCV를 잘 불러오는지 확인해봅니다.
pi@RaspberryPi3:~/opencv/build/ $ python3 Python 3.4.2 (default, Oct 19 2014, 13:31:11) [GCC 4.9.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import cv2 >>> print(cv2.__version__) 3.2.0 >>> exit() pi@RaspberryPi3:~/opencv/build/ $