OpenCV 설치와 관련된 블로그를 읽다보면 TBB를 함께 설치하라는 글을 종종 찾을 수가 있습니다. TBB는 Threading Building Blocks의 약자이고, Intel에서 만든 다중 코어, 멀티 쓰레드 라이브러리입니다. 대용량 데이터인 영상을 처리할 때 여러 개의 쓰레드를 사용하여 연산을 좀 더 빠르게 수행할 수 있게 해주는 역할을 하는 라이브러리 입니다.

https://www.threadingbuildingblocks.org/

TBB는 예전에는 GPL 라이센스를 따르다가 TBB 2017 버전부터는 Apache v2.0 라이센스를 따르기 때문에 사용하기가 좀 더 자유로와졌습니다.


그렇다면 OpenCV를 직접 빌드하여 설치할 때 TBB를 함께 설치하면 효과적이겠지요? 멀티 쓰레드를 사용하여 연산 시간이 몇 배 빨라질 수 있으니까요. 그렇지만 굳이 번거롭게 TBB를 설치하지 않아도 최신 버전의 OpenCV에서는 멀티 쓰레드 프로그래밍을 기본 지원합니다. 오늘은 이 부분에 대해 정리하려고 합니다.


먼저 아래 링크를 살펴보면 이런 말이 쓰여 있습니다.

http://code.opencv.org/projects/opencv/wiki/ChangeLog#243


즉, OpenCV 2.4.3 버전부터 TBB 뿐만 아니라 OpenMP, GCD, Concurrency 같은 멀티 쓰레드 기법을 이용하여 OpenCV 코드가 동작한다는 의미입니다. 일단 저는 Windows 운영 체제에서 Visual Studio를 주로 이용하는데요, Visual Studio 2010 버전 이상부터는 MS의 Concurrency라는 이름의 멀티 쓰레드 기법이 기본으로 적용됩니다. 즉, 굳이 TBB를 깔지 않아도 Concurrency 기법을 통해 병렬 프로그래밍이 동작한다는 의미이죠. (몇몇 블로그에서 소개하는 TBB 설치 관련 얘기는 2013년 이전에 사용되는 기법입니다. 현재는 굳이 TBB를 사용하지 않아도 된다는 것이죠)


실제로 OpenCV 소스 코드 중에서 <opencv>/modules/core/src/Parallel.cpp 파일을 보면 아래와 같은 형태로 코드가 작성이 되어 있습니다.

void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, double nstripes)
{
    CV_INSTRUMENT_REGION_MT_FORK()
    if (range.empty())
        return;

#ifdef CV_PARALLEL_FRAMEWORK

    if(numThreads != 0)
    {
        ProxyLoopBody pbody(body, range, nstripes);
        cv::Range stripeRange = pbody.stripeRange();
        if( stripeRange.end - stripeRange.start == 1 )
        {
            body(range);
            return;
        }

#if defined HAVE_TBB

        tbb::parallel_for(tbb::blocked_range(stripeRange.start, stripeRange.end), pbody);

#elif defined HAVE_CSTRIPES

        parallel(MAX(0, numThreads))
        {
            int offset = stripeRange.start;
            int len = stripeRange.end - offset;
            Range r(offset + CPX_RANGE_START(len), offset + CPX_RANGE_END(len));
            pbody(r);
            barrier();
        }

#elif defined HAVE_OPENMP

        #pragma omp parallel for schedule(dynamic)
        for (int i = stripeRange.start; i < stripeRange.end; ++i)
            pbody(Range(i, i + 1));

#elif defined HAVE_GCD

        dispatch_queue_t concurrent_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_apply_f(stripeRange.end - stripeRange.start, concurrent_queue, &pbody, block_function);

#elif defined WINRT

        Concurrency::parallel_for(stripeRange.start, stripeRange.end, pbody);

#elif defined HAVE_CONCURRENCY

        if(!pplScheduler || pplScheduler->Id() == Concurrency::CurrentScheduler::Id())
        {
            Concurrency::parallel_for(stripeRange.start, stripeRange.end, pbody);
        }
        else
        {
            pplScheduler->Attach();
            Concurrency::parallel_for(stripeRange.start, stripeRange.end, pbody);
            Concurrency::CurrentScheduler::Detach();
        }

#elif defined HAVE_PTHREADS_PF

        parallel_for_pthreads(pbody.stripeRange(), pbody, pbody.stripeRange().size());

#else

#error You have hacked and compiling with unsupported parallel framework

#endif

    }
    else

#endif // CV_PARALLEL_FRAMEWORK
    {
        (void)nstripes;
        body(range);
    }
}

즉, TBB, OpenMP, GCD, Concurrency, pthread 중 어느 것 하나만이라도 있으면 OpenCV는 멀티 쓰레드 형태로 동작을 하게 되고, 병렬 처리를 하기 때문에 빠르게 동작한다는 것이죠.


참고로 Visual Studio 버전이 2010 이상 버전이면 HAVE_CONCURRENCY가 자동으로 #define 됩니다. 라즈베리파이같은 리눅스 머신에서는 pthread가 자동으로 동작합니다.


그렇다면 TBB랑 OpenMP, Concurrency 같은 것들끼리 성능 차이가 얼마나 있을까요? 같은 병렬 프로그래밍이라고 하더라도 TBB가 더 효과적으로 잘 동작한다면 Visual Studio에서 기본 지원하는 Concurrency 보다는 TBB를 깔아서 쓰는 것이 더 좋지 않을까요?? 저도 이런 의문을 가지고 구글링을 열심히 해보았는데요, 뚜렷한 성능 비교 결과를 찾지 못했습니다. 그러나 좀 더 생각을 해보니, 어차피 OpenCV에서 큰 성능 향상을 얻으려면 병렬 프로그래밍보다는 CUDA 또는 OpenCL 쪽을 더 고민해보는 것이 맞지 않을까 생각합니다.


그래서 제 결론은, "Visual Studio 사용할 때에는 그냥 기본 Concurrency 라이브러리를 사용하자"입니다. 굳이 번거롭게 TBB를 깔지 않아도 됩니다. (TBB을 이용해서 빌드하면 프로그램 배포 시 tbb.dll 파일도 함께 배포해야 합니다.)


참고로 Visual Studio의 Concurrency에 대한 내용은 아래 유투브 동영상을 참고하시면 좋습니다. 아래 동영상에서 설명하는 Auto Parallelization이라는 것이 Concurrency와 같은 내용입니다.

https://youtu.be/dYx24RbQsY8



Posted by kkokkal
:

지난 번 "Visual Studio 2017에서 OpenCV 3.2 빌드하기"에 이어 이번에는 OpenCV Extra module을 함께 빌드하는 방법을 정리해보겠습니다. 더불어 Python을 이용하여 OpenCV를 사용하기 위해 python 개발 환경을 만드는 것도 함께 알아봅니다.


추후 OpenCV를 Python 언어로 사용하려면 OpenCV를 빌드하기 전에 미리 Python을 컴퓨터에 설치해두어야 합니다. 개인적으로는 Python을 직접 설치하는 방법 대신, Anaconda를 설치하여 Python과 유용한 라이브러리를 한꺼번에 설치했습니다. 제가 설치한 Anaconda 버전은 4.4.0이고, 이 패키지에 들어있는 Python 버전은 3.6.1 입니다. Anaconda는 아래 링크에서 다운로드 할 수 있습니다.

https://www.continuum.io/downloads


참고로, Anaconda 4.4.0 버전을 설치할 때에는 Anaconda 관련 패스를 환경 변수에 추가하지 않는 것을 권장하는데요, 저는 그냥 환경 변수를 추가하여 설치를 했습니다.


이제 본격적으로 OpenCV를 빌드하는 방법을 알아보겠습니다. 먼저 OpenCV Extra modules 소스 코드를 다운로드 합니다. OpenCV Extra modules의 최신 소스 코드는 https://github.com/opencv/opencv_contrib 사이트에서 다운받을 수 있습니다. 다만 지금 빌드할 버전은 2016년 12월에 릴리즈된 OpenCV 3.2 버전이기때문에 아래 링크에서 소스 코드를 다운로드합니다.

https://github.com/opencv/opencv_contrib/releases/tag/3.2.0


위 사이트에서 Source code (zip) 으로 링크된 zip 파일을 다운로드하면 opencv_contrib-3.2.0.zip 이름으로 소스 코드가 다운로드 됩니다. 이 파일을 이전에 OpenCV 소스 코드 압축을 풀었던 C:\OpenCV 폴더에서 압축을 풉니다. 그러면 C:\OpenCV\opencv_contrib-3.2.0 폴더가 생기면서 그 아래에 여러 개의 폴더와 파일이 생성됩니다.


OpenCV Extra Modules와 함께 OpenCV 3.2를 빌드하는 방법은 "Visual Studio 2017에서 OpenCV 3.2 빌드하기"에서 설명한 방법과 거의 유사합니다. 가장 큰 차이점은 CMake 프로그램에서 Extra modules 소스 코드가 있는 폴더 위치를 지정해주어야 한다는 점인데요, 그 외에도 몇 가지 다른 점이 있으니 아래 내용을 잘 읽으시기 바랍니다.


소스 코드가 제대로 준비되었으면 이제 CMake를 실행합니다. 혹시 이전에 CMake에서 설정했던 내용이 기억되어 있을 경우 새로 빌드하는 과정에서 예상치못한 에러가 발생할 수도 있으니 [File] -> [Delete Cache] 메뉴를 한 번 실행하는 것을 권장합니다. 그리고 (예전에 했던 것과 동일하게) Where is the source code: 에는 C:\opencv\opencv-3.2.0 폴더를 선택하고, Where to build the binaries: 항목은 C:\opencv\mybuild 폴더를 선택합니다. 그리고 [Configure] 버튼을 클릭하고, "Visual Studio 15 2017 Win64" 항목을 선택합니다.


CMake 설정에서 변경해야할 사항은 아래와 같습니다.

  • BUILD_EXAMPLES: 선택 (Optionial)
  • BUILD_opencv_world: 선택 안함 (기본값 변경 안함)
  • INSTALL_PYTHON_EXAMPLES: 선택 (Optional)
  • OPENCV_EXTRA_MODULES_PATH: C:/opencv/opencv_contrib-3.2.0/modules
  • WITH_CUDA: 선택 해제 (VS2017 지원 안함)
  • WITH_OPENGL: 선택 (Optionial)


위 설정에서 중요한 것은 OPENCV_EXTRA_MODULES_PATH 항목을 C:/opencv/opencv_contrib-3.2.0/modules 로 지정하는 것입니다. C:/opencv/opencv_contrib-3.2.0/ 폴더가 아니라 그 아래에 있는 modules 폴더를 지정해야 합니다.


그리고 이전에 OpenCV 기본 소스 코드만 빌드할 때에는 BUILD_opencv_world 항목을 선택해서 빌드를 했지만, opencv_contrib 소스까지 함께 빌드할 때에는 BUILD_opencv_world 항목을 선택하면 에러가 발생합니다. 이는 OpenCV 3.2 릴리즈 버전의 소스 코드를 빌드할 때 발생하는 문제인데요, 일종의 버그라고 보시면 됩니다. 좀 더 최신의 OpenCV 소스 코드를 사용하여 빌드하면 BUILD_opencv_world 항목을 선택하여 빌드하여도 문제가 발생하지 않는데요, 일단 정식으로 릴리즈된 3.2 버전에 대해서는 위와 같은 형태로 선택하시는 것이 좋습니다.


Python과 관련된 설정을 살펴보면 Python3 관련 설정을 자동으로 되어 있고, Python2 관련 설정은 비어있는 것을 확인할 수 있습니다. (물론 이것은 제 시스템 설정과 관련된 것이고, 혹시라도 Python2를 설치하였다면 관련 항목이 보이는 것이 맞습니다.)


일단 위의 설정을 완료했으면 [Configure] 버튼을 다시 클릭합니다. 그리고 약간의 시간이 지나면 아래와 같은 화면이 나타납니다.


이전에 OpenCV 기본 소스만 설정할 때에는 [Configure] 버튼을 클릭하면 곧바로 모든 항목의 빨간색이 사라졌는데요, 이번에는 Extra modules 관련된 설정이 빨간색으로 새로 나타납니다. 특별히 설정을 변경할 것이 없다면 그대로 다시 [Configure] 버튼을 클릭합니다. 그리고 에러 발생 없이 모든 항목이 흰색으로 바뀌면 [Generate] 버튼을 클릭합니다. 아래에 제 PC의 설정을 아래 [더보기]에 요약해두었습니다.


OpenCV.sln 파일이 정상적으로 생성되면 Visual Studio 2017에서 열어서 빌드 작업을 수행합니다. Debug 모드와 Release 모드로 각각 전체 솔루션 빌드를 수행하고, 이후 INSTALL 프로젝트를 따로 빌드합니다. Debug 모드에서는 Python 프로젝트가 실패하기 때문에 실패 1이 나타날 수 있습니다. Release 모드는 실패 없이 402건 모두 성공했습니다.


정상적으로 빌드가 완료되었기 때문에 Python에서도 OpenCV를 사용할 수 있습니다. 도스창을 열어서 테스트해보면 OpenCV 버전이 잘 출력되는 것을 확인할 수 있습니다.




Posted by kkokkal
:

OpenCV는 Open Source Computer Vision Library이고, 2500개가 넘는 최신 컴퓨터 비전 알고리즘과 머신 러닝 알고리즘을 지원합니다. OpenCV는 BSD 라이선스를 따르고 있기 때문에 학계 연구용이나 상업적인 용도로 자유롭게 사용할 수 있습니다. 2017년 6월 현재, OpenCV 최신 버전은 3.2이고, http://www.opencv.org/ 웹사이트에서 Windows용 설치 버전을 다운받을 수 있습니다. 그러나 OpenCV 3.2 Windows 설치 버전은 Visual Studio 2015 버전으로 빌드되어 있는 DLL, LIB 파일만을 제공하기 때문에 Visual Studio 최신 버전인 Visual Studio 2017에서 사용하려면 소스 코드를 직접 빌드하여 사용하는 것이 좋습니다.


OpenCV를 처음 접하는 분들에게 당부드리는 말씀

OpenCV는 2006년 처음 1.0 버전이 나온 후 2015년에 OpenCV 3.0이 발표되었습니다. 버전이 올라가면서 IplImage 구조체를 사용하는 C언어 인터페이스에서 Mat 클래스를 사용하는 C++ 인터페이스로 발전하였고, 내부적으로 많은 구조적인 변화가 생겼습니다. 그럼에도 아직까지도 OpenCV 1.x 버전의 문법으로 되어 있는 소스 코드가 인터넷에 많이 돌아다니고 있는 현실인데요, 이제 새로 OpenCV를 배우는 분들은 과거의 문법과 구조를 사용하지 마시고 최신 OpenCV 3.x 버전에 맞는 문법을 배우시라고 권해드리고 싶습니다.


OpenCV 라이브러리를 설치하는 과정은 다음 순서를 따릅니다.

    1. Visual Studio 설치하기
    2. CMake 설치하기
    3. OpenCV 소스 코드 다운로드
    4. CMake 프로그램으로 솔루션 파일, 프로젝트 파일 생성하기
    5. Visual Studio에서 OpenCV 빌드하기
    6. OpenCV 설치하기


Visual Studio 설치하기

2017년 현재, Visual Studio 최신 버전은 Visual Studio 2017입니다. https://www.visualstudio.com/ 사이트에 접속하면 Visual Studio 2017 Community Edition을 무료로 다운로드 받아 설치할 수 있습니다. Visual Studio를 설치하는 방법은 자세히 설명하지 않으며, 다만 설치시 "C++를 사용한 데스크톱 개발" 항목은 반드시 선택하여 설치해야 합니다.


CMake 설치하기

CMake 프로그램은 다양한 운영 체제 또는 프로그래밍 개발 환경에 적합한 Make 파일(또는 프로젝트, 솔루션 파일)을 생성하는 유틸리티입니다. 즉, OpenCV 소스 코드로부터 Visual Studio 2017용 솔루션 파일(*.sln)과 프로젝트 파일(*.vcxproj) 파일을 생성해주는 프로그램이라고 생각하시면 됩니다. CMake 프로그램은 https://cmake.org/download/ 사이트에서 다운로드 받을 수 있으며, 3.8.0 이상 버전을 사용하시면 됩니다. CMake 설치는 크게 복잡하지 않으며 자세한 설명은 생략합니다.


OpenCV 소스 코드 다운로드

OpenCV 최신 소스 코드는 https://github.com/opencv/opencv 에서 다운받을 수 있습니다. 다만 이 글에서 사용할 소스 코드는 OpenCV 3.2 버전으로 배포된 소스 코드입니다. OpenCV 3.2 버전의 소스 코드는 OpenCV 3.2 설치 버전에도 들어있지만, 아래 링크에서 순수한 소스 코드만 다운받을 수 있습니다. Windows 환경이니 편리하게 Source code (zip) 파일을 선택하여 다운로드 하시면 됩니다. 

https://github.com/opencv/opencv/releases/tag/3.2.0


CMake 프로그램으로 솔루션 파일, 프로젝트 파일 생성하기

이제부터 본격적인 소스 코드 빌드를 위한 작업을 설명합니다. 저는 C 드라이브 아래 opencv 라는 폴더를 만들고, 그 아래에서 소스 코드 압축을 해제하고 빌드 작업을 수행할 것입니다. 그러므로 C:\opencv\ 폴더를 생성하고, 그 아래에 opencv-3.2.0.zip 파일의 압축을 해제합니다. 그러면 C:\opencv\opencv-3.2.0 폴더 아래에 여러 개의 폴더와 파일이 생성됩니다. 그리고 실제 빌드 작업은 C:\opencv\mybuild 라는 이름의 폴더를 만들고, 그 안에서 DLL 파일과  LIB 파일을 생성할 것입니다. 즉, 우선 디렉토리 구조를 아래 그림처럼 생성합니다. (일단 opencv_contrib-3.2.0 폴더는 신경쓰지 않아도 됩니다.)


이제 CMake (cmake-gui) 프로그램을 실행합니다. CMake 프로그램에서 Where is the source code: 에는 C:\opencv\opencv-3.2.0 폴더를 선택하고, Where to build the binaries: 항목은 C:\opencv\mybuild 폴더를 선택합니다. 아래 그림처럼 선택을 하였으면 왼쪽 아래 [Configure] 버튼을 클릭합니다.


[Configure] 버튼을 클릭하면 아래와 같은 창이 나오는데요, 상단의 콤보 박스 항목 중에서 "Visual Studio 15 2017 Win64"를 선택합니다. Visual Studio 2017 버전을 사용할 것이고, 64비트로 컴파일하고 빌드할 것입니다. 만약 사용하고 있는 Windows 운영체제가 아직도 32비트 버전이라면 64비트 버전으로 갈아타는 것을 추천합니다. 그 아래 옵션은 기본값을 그대로 사용하기로 하고 [Finish] 버튼을 클릭합니다.


CMake 프로그램은 현재 PC의 설정을 확인하고, 추가적으로 빌드에 필요한 파일을 인터넷을 통해 다운로드 받습니다. 얼마간의 시간이 흐르면 아래와 같은 그림이 나타납니다. 가운데 영역이 빨간색 배경으로 나온 것이 왠지 살짝 섬뜩한데요, 여기서 OpenCV 빌드를 위한 옵션을 선택할 수 있습니다. 이 과정이 OpenCV를 설치하는 과정 중에서 가장 중요한 부분입니다. 다소 생소해보일수도 있지만 주의깊게 잘 생각해서 옵션을 선택해야 합니다.

참고로 제 PC에서 나타난 Configuration message는 아래와 같습니다.


저는 기본으로 선택된 옵션 중에서 아래 몇가지 항목을 추가로 설정했습니다.

    • BUILD_EXAMPLES: 선택
    • BUILD_opencv_world: 선택
    • WITH_CUDA: 선택 해제 (VS2017 지원 안함)
    • WITH_OPENGL: 선택

BUILD_opencv_world 옵션을 선택하면 opencv_core320.dll, opencv_imgproc320.dll, opencv_highgui320.dll 같이 여러 개로 생성되는 DLL 파일들이 하나의 opencv_world320.dll 파일로 합쳐져서 빌드가 됩니다. 그러므로 소스 코드를 작성할 때에도 하나의 opencv_world320.lib 파일만 링크해서 사용하면 되기 때문에 편리합니다. 다만 효율성과 용량의 문제를 고려한다면 BUILD_opencv_world 옵션을 사용하지 않는 것이 좋은 선택일 겁니다.


일단의 선택을 마치면 다시 [Configure] 버튼을 클릭합니다. 그러면 CMake 중앙의 빨간색 배경의 옵션들이 모두 흰색 배경으로 변경됩니다. 이제 [Generate] 버튼을 클릭하면 C:\opencv\mybuild 폴더에 OpenCV.sln 파일이 생성됩니다.


Visual Studio에서 OpenCV 빌드하기

Visual Studio 2017 Community Edition을 실행하여 OpenCV.sln 솔루션 파일을 오픈합니다. 또는 C:\opencv\mybuild 폴더에서 OpenCV.sln 파일을 더블클릭하면 Visual Studio 2017이 실행됩니다. 그러면 아래 그림같은 화면이 나타납니다.

그리고 위에 그림처럼 [빌드] -> [솔루션 빌드] 메뉴 항목을 선택하면 OpenCV 소스 코드를 빌드하기 시작합니다. 이 작업은 PC 사양에 따라 조금 다르겠지만 대략 20분 내외의 시간이 소요됩니다.


빌드 작업이 끝나면 아래 그림의 하단 출력창처럼 빌드: 성공 202, 실패 0, 최신 0, 생략 7 같은 메시지가 나타납니다. 성공 프로젝트 개수는 CMake 옵션을 어떻게 주었느냐에 따라 다를 수 있습니다. 다만 실패 작업이 너무 많이 나타난다면 opencv_world320d.lib 빌드가 잘 되었는지를 확인하고, 문제가 있다면 CMake 작업부터 다시 시도하기 바랍니다.


OpenCV 설치하기

Visual Studio에서 빌드가 정상적으로 완료가 되었다고해서 완전히 끝난 것이 아닙니다. OpenCV를 빌드하면 DLL과 LIB 파일들이 생성되는데, 이 파일들을 한 곳에 모아서 작업하는 것이 좋습니다. 특히 OpenCV에서 사용하는 헤더파일은 C:\opencv\opencv-3.2.0\modules 폴더 아래에 산재해있기 때문에 이 파일들을 정해진 폴더에 옮기는 작업을 수행해야 합니다.


이 작업은 OpenCV 솔루션 중에서 INSTALL이라는 이름의 프로젝트를 이용하여 수행할 수 있습니다. 아래 그림처럼 현재 열려있는 프로젝트 중에서 INSTALL 이라는 이름의 프로젝트를 마우스로 선택하고, 여기서 마우스 오른쪽 버튼을 클릭하여 [빌드] 메뉴를 선택합니다.


위 작업이 완료되면 c:\opencv\mybuild\install\ 폴더 아래에 OpenCV 관련 헤더 파일, DLL 파일, LIB 파일들이 모여지게 됩니다. DLL 파일은 c:\opencv\mybuild\install\x64\vc15\bin\ 폴더로 복사되고, LIB 파일은 c:\opencv\mybuild\install\x64\vc15\lib\ 폴더로 복사됩니다. 헤더 파일은 c:\opencv\mybuild\install\include\ 폴더 아래로 모두 모이게 되는데, 탐색기로 이 위치를 살펴보면 아래와 같습니다.


이제 OpenCV를 Visual Studio에서 Debug 모드로 빌드하는 작업이 완료되었습니다. 이 작업을 이제 Release 모드로도 똑같이 반복합니다. 아래 그림처럼 현재 구성을 Debug 모드에서 Release 모드로 변경하고, 다시 [빌드] -> [솔루션 빌드] 메뉴를 선택합니다. 그리고 빌드가 완료되면 다시 INSTALL 프로젝트를 빌드하면 됩니다.



여기까지가 기본적인 OpenCV 라이브러리 빌드 방법이었습니다.


Posted by kkokkal
: