올해 2월에 조립 PC를 새로 장만해서 Visual Studio 2015를 깔았고, 이후 Visual Studio 2017 버전이 나와서 Visual Studio 2015를 지우고 Visual Studio 2017만 사용하려고 했었습니다. 그런데 nVidia Cuda가 Visual Studio 2017을 아직 지원하지 않아서 다시 Visual Studio 2015를 설치를 했습니다. 그리고나서 OpenCV 최신 소스를 Visual Studio 2015로 새로 빌드하려고 CMake에서 "Visual Studio 14 2015 Win64"를 선택했는데, 이상한 에러가 발생하네요.



The CXX compiler identification is unknown
The C compiler identification is unknown


일단 눈으로 보이는 에러 메시지는 CXX, C 컴파일러를 찾지 못한다는 것인데요, 자세한 내용을 확인하기 위해 C:/opencv/mybuild/CMakeFiles/CMakeOutput.log 파일을 열어보았습니다.


Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" failed.
Compiler: 
Build flags:
Id flags: 

The output was:
1
Microsoft (R) Build Engine 버전 14.0.25420.1]
Copyright (C) Microsoft Corporation. All rights reserved.

빌드 시작: 2017-08-03 오전 10:47:35
1 노드의 "C:\opencv\mybuild\CMakeFiles\3.9.0\CompilerIdCXX\CompilerIdCXX.vcxproj" 프로젝트(기본 대상)입니다.
PrepareForBuild:
  "Debug\" 디렉터리를 만들고 있습니다.
  "Debug\CompilerIdCXX.tlog\" 디렉터리를 만들고 있습니다.
InitializeBuildStatus:
  "AlwaysCreate"이(가) 지정되었기 때문에 "Debug\CompilerIdCXX.tlog\unsuccessfulbuild"을(를) 만들고 있습니다.
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\CL.exe /c /nologo /W0 /WX- /Od /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"Debug\\" /Fd"Debug\vc140.pdb" /Gd /TP /errorReport:queue CMakeCXXCompilerId.cpp
  CMakeCXXCompilerId.cpp
Link:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\link.exe /ERRORREPORT:QUEUE /OUT:".\CompilerIdCXX.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdCXX.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdCXX.lib" /MACHINE:X64 Debug\CMakeCXXCompilerId.obj
LINK : fatal error LNK1158: 'rc.exe'을(를) 실행할 수 없습니다. [C:\opencv\mybuild\CMakeFiles\3.9.0\CompilerIdCXX\CompilerIdCXX.vcxproj]
"C:\opencv\mybuild\CMakeFiles\3.9.0\CompilerIdCXX\CompilerIdCXX.vcxproj" 프로젝트를 빌드했습니다(기본 대상). - 실패

빌드하지 못했습니다.

"C:\opencv\mybuild\CMakeFiles\3.9.0\CompilerIdCXX\CompilerIdCXX.vcxproj"(기본 대상)(1)->
(Link 대상) ->
  LINK : fatal error LNK1158: 'rc.exe'을(를) 실행할 수 없습니다. [C:\opencv\mybuild\CMakeFiles\3.9.0\CompilerIdCXX\CompilerIdCXX.vcxproj]

    경고 0개
    오류 1개

경과 시간: 00:00:00.81

...


중간에 보면 rc.exe 를 실행할 수 없다는 메시지가 나타납니다. rc.exe는 "Microsoft (R) Windows (R) Resource Compiler"를 의미하는 것인데, 이 파일을 찾을 수 없다는 의미인거네요. 시작 메뉴에서 "Visual Studio 2015 Tools 명령 프롬프트 열기" 메뉴를 찾아서 실행하고, 나타난 도스창에서 rc.exe를 입력하면 실제로도 해당 파일을 찾을 수 없다고 나타납니다.


이와 반대로 "Open Visual Studio 2017 Tools Command Prompt" 커맨드 창에서는 rc.exe /? 명령을 실행하면 아래와 같이 프로그램이 잘 실행됩니다.


결국 원인을 알 수 없는 이유로 인하여 Visual Studio 2015 환경에서는 rc.exe 파일을 찾지 못한다는 것이고, 이는 기본적으로 Visual Studio 2017 커맨드창 환경과 Visual Studio 2015 커맨드창의 PATH 설정이 다르기 때문일 것입니다. 그래서 두 창에서 각각 PATH 명령을 입력해서 그 차이를 비교해보고, 실제 rc.exe 파일이 있는 위치를 검토해보니 아래 디렉토리가 PATH에 있느냐 없느냐의 차이인 것으로 보였습니다.


C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x86


바로 이 폴더에 Windows SDK 버전 10의 rc.exe 파일이 있네요. 그러므로 Visual Studio 2015 버전에서도 이 디렉토리를 PATH 환경 변수에 추가해주면 되는데요, 음.. 반대로 위 폴더에 있는 rc.exe 파일을 Visual Studio 2015 커맨드창 PATH 경로에 복사해주어도 정상적으로 동작을 합니다. 그래서 해결책은 이렇습니다.


1. C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x86 폴더에서

2. rc.exe 파일과 rcdll.dll 파일을 복사해서

3. C:\Program Files (x86)\Windows Kits\10\bin\x86\ 폴더에 붙여넣습니다.


그랬더니 CMake가 잘 동작을 하네요~ :-)



Posted by kkokkal
:

Notepad++에서 Python을 실행하는 방법에 대해 정리해보겠습니다. 사실 요즘은 Notepad++보다 더 화려하고 Python과도 잘 어울리는 편집기도 많이 있는데요(예를 들어, Sublime Text, Atom, Visual Studio Code...), 개인적으로는 아직까지 Notepad++가 편하고 무난해서 자주 사용하고 있습니다.


Notepad++에서 Python 코드를 편집하고, Notepad++ 안에서 곧바로 실행시켜서 결과를 확인하려면 일단 Notepad++의 플러그인을 설치해야 하는데요, 설치할 플러그인의 이름은 NppExec 입니다. 말 그대로 Npp, 노트패드 플러스 플러스에서 Exec, 무언가를 실행할 수 있게 해주는 플러그인입니다. NppExec 플러그인은 Notepad++ 메뉴 중 [플러그인] -> [Plugin Manager] -> [Show Plugin Manager]를 선택하여 나타나는 리스트 중에 NppExec를 선택하여 추가할 수 있습니다. 만약 Notepad++ 64비트 버전을 사용하고 있다면 Plugin Manager를 수동으로 미리 설치를 해야 하는데요, 아래 링크에서 최신 버전을 다운받아 Notepad++ 설치 폴더 아래에 적당히 압축을 풀어주면 됩니다.

https://github.com/bruderstein/nppPluginManager/releases



일단 NppExec 플러그인을 설치하면 Notepad++ [플러그인] 메뉴 항목 아래에 NppExec 메뉴 항목이 새로 생깁니다. 일단 여기서 [Follow $(CURRENT_DIRECTORY)] 항목은 선택을 해두는 것이 좋습니다. 그렇지 않으면 파이썬 코드에서 파일 입출력을 할 때 예상치 못한 형태로 동작할 수 있습니다.


그리고 *.py로 끝나는 파이썬 프로그램 코드를 하나 열어서 [플러그인] -> [NppExec] -> [Execute] 메뉴를 선택하거나, 또는 단축키 F6을 누릅니다. 그러면 아래와 같은 NppExec 실행 창이 나타납니다.


Execute 창에는 실제 실행할 명령어를 입력하는데요, 아래와 같이 입력합니다.

NPP_SAVE
python "$(FULL_CURRENT_PATH)"


여기서 NPP_SAVE 명령은 프로그램을 실행하기 전에 파일을 저장하도록 하는 명령이고, 두 번째 줄이 실제 파이썬 프로그램으로 해당 *.py 파일을 실행하는 명령입니다. 명령어를 제대로 입력하고, 나중에 다시 사용하기 편하도록 [Save...] 버튼을 클릭하여 파이썬 실행을 위한 명령어를 기록해둡니다. 저는 python 이라는 제목으로 명령어를 저장해두었기에 그림 왼쪽 아래 콤보 박스에 python 이라고 써있습니다. 명령어 저장을 했으면 [OK] 버튼을 누릅니다. 그러면 아래와 같이 python 프로그램 실행 결과가 Console 창에 나타납니다.


참 쉽죠??


참고로 Python 실행 결과가 나타나는 Console 창의 폰트를 바꾸고 싶으면 [플러그인] -> [NppExec] -> [Change Console Font...] 메뉴를 선택하여 폰트를 변경할 수 있습니다.



'Study > Python' 카테고리의 다른 글

Jupyter Notebook 폰트 바꾸기  (0) 2017.10.15
Posted by kkokkal
:

패스트캠퍼스에서 진행하고 있는 OpenCV 강의에서 사용되는 예제 프로그램은 100개가 훨씬 넘습니다. 매번 새로운 강의가 시작될 때마다 Visual Studio 버전이 바뀌거나 OpenCV 라이브러리 버전이 바뀌면 모든 프로젝트를 새로 빌드해서 테스트를 진행하는데요, 100개가 넘는 프로젝트를 Visual Studio에서 불러와서 하나씩 하나씩 컴파일하고 빌드하려고 하면 너무 번거롭습니다. 그래서 일괄 빌드 방법을 알아봤습니다.


일단 저의 OpenCV 강의는 8주 과정으로 이루어져있기 때문에 "1주차_예제_코드", "2주차_예제_코드", ... 같은 형태의 폴더가 있고, 그 아래에 여러 개의 예제 프로젝트 폴더를 만들어두었습니다. 그러므로 현재 폴더에서 "N주차_예제_코드" 폴더를 모두 찾고, 그 아래에 있는 폴더들에 각각 들어가서 예제 프로젝트를 빌드해야 합니다. 이 작업을 수행하는 배치 파일 build_all.bat 파일을 아래와 같이 작성했습니다.


@ECHO OFF

SET CURR=%CD%
ECHO Current dir: %CURR%

FOR /D %%i IN (%CURR%\*) DO (
  PUSHD %%i
  ECHO Check sub-dir in %%i

  FOR /D %%k IN (%%i\*) DO (
    PUSHD %%k

    ECHO Now in %%k

    IF EXIST "*.vcxproj" (
      ECHO Build the project in %%k
	  
      msbuild /t:Rebuild /p:Configuration=Release
      copy .\x64\release\*.exe .
      rmdir x64 /S /Q
	  
    ) ELSE (
      ECHO No project in %%k
    )	

    POPD 
  )

  POPD 
)


위 배치 파일은 현재 폴더에서 하위 폴더들을 모두 찾고, 각각의 하위 폴더에서 또 한번 하위 폴더들을 찾아서 방문하고, 해당 폴더에 *.vcxproj 파일이 있는 경우에는 해당 프로젝트를 Release 모드로 빌드합니다. 그리고 생성된 ./release/<proj_name>.exe 파일을 프로젝트 폴더쪽으로 복사한 후, release 폴더는 지워버립니다. 그러면 나중에 실행 파일을 쉽게 실행하여 결과를 볼 수 있기 때문에 유용하죠.


아래는 실제로 build_all.bat 파일을 실행했을 때의 결과입니다. (프로젝트 몇 개만 복사해서 테스트해봤습니다.)


위에 나타난 도스창은 CMD 또는 일반 명령 프롬프트가 아니라 시작 메뉴에서 Developer Command Prompt for VS 2017 라는 이름을 검색해서 실행한 창입니다. Visual Studio 프로젝트 빌드를 위한 환경 설정이 적용된 창이라서 msbuild라는 이름의 빌드 명령을 사용할 수 있습니다.


만약 현재 폴더 아래의 하위 폴더에 존재하는 모든 프로젝트를 빌드하려면 위 배치 파일을 아래처럼 변경하면 되겠죠?

@ECHO OFF

SET CURR=%CD%
ECHO Current dir: %CURR%

FOR /D %%i IN (%CURR%\*) DO (
  PUSHD %%i
  ECHO Check sub-dir in %%i

  IF EXIST "*.vcxproj" (
    ECHO Build the project in %%i
	  
    msbuild /t:Rebuild /p:Configuration=Release
    copy .\x64\release\*.exe .
    rmdir x64 /S /Q
	  
  ) ELSE (
    ECHO No project in %%i
  )	

  POPD 
)


한 가지 주의할 점은, 빌드하려고 하는 전체 경로 이름에 빈칸이 있으면 안됩니다. 배치 파일의 FOR 구문에서 빈칸에 대해서는 제대로 처리를 하지 못하네요.


Posted by kkokkal
:

라즈베리파이 PIXEL 데스크탑에서 사용할 수 있는 화면 캡쳐 프로그램 scrot 사용법을 정리합니다.


scrot는 SCReenshOT의 약자이며, 말 그래도 화면 캡처를 하는 프로그램입니다. 기본적으로 텍스트 기반의 프로그램이며 일단 터미널 창에서 scrot -h 라고 입력하면 도움말을 보여주는데, 중요한 명령어가 위로 빨리 올라가버리니까 scrot -h | more 라고 입력하여 명령어를 확인합니다.


개인적으로 자주 쓰는 옵션은 -d, -u, -b 입니다.


-d는 delay를 의미하고, 보통 -d 5 처럼 바로 뒤에 숫자를 쓰면 해당하는 시간(초단위) 이후에 캡쳐를 합니다. 예를 들어, 웹브라우저가 떠있는 전체 화면을 캡쳐하려면 터미널 창을 하나 띄우고 여기에 scrot -d 5 라고 입력하고 터미널 창을 최소화하여 기다립니다.


-u 옵션은 현재 활성화된 왼도우만을 캡쳐하고 싶을 때 사용합니다. 예를 들어, 터미널 창을 2개 띄워놓고 ls 화면을 캡쳐하려면 다른 창에서 scrot -d 5 -u 라고 입력하고, 5초 안에 ls 명령을 내린 터미널 창을 클릭하여 활성화 시킵니다.


그런데 -u 옵션만 사용하면 윈도우 타이틀바와 테두리를 함께 캡쳐하지를 않네요. 뭔가 약간 어색해서, 보통은 -b 옵션을 같이 줘서 border까지 함께 캡쳐를 합니다. scrot -d 5 -u -b 라고 입력해도 되고, scrot -d 5 -ub 라고 입력해도 됩니다.


이렇게 캡쳐한 화면은 바로 위 터미널 ls 화면에 보라색 글씨로 나타난 것처럼 <날짜>-<시간>-<해상도>_scrot.png 형태의 이름으로 저장됩니다. 화면 캡쳐니까 png 파일 포맷이 적당해보입니다.


단축키도 지원을 하는데요, PrtSc 키를 누르면 전체 화면을 저장합니다. 음.. PrtSc 키에 대해서 scrot 화면 캡쳐를 하는 것은 ~/.config/openbox/lxde-pi-rc.xml 파일에서 키바인딩이 기본으로 되어 있기 때문인데요..


만약 ALT + PrtSc 키에 대해 현재 활성화된 화면 캡쳐를 수행하도록 하고, CTRL + PrtSc 키에 대해 윈도우 선택 또는 사각형 영역 지정 캡쳐를 수행하려면 아래와 같이 lxde-pi-rc.xml 파일을 편집하면 됩니다. (287~296라인) 그리고 재부팅 또는 openbox --reconfigure 명령을 입력하면 됩니다.



Posted by kkokkal
:

아주 단순하게, 가우시안 필터와 캐니 엣지 검출에 대해서만 OpenCV 3.2 vs. OpenCV 3.3.0-rc 두 버전 간의 성능을 비교해봤습니다.


소스 코드는 매우 단순하게 레나 영상을 불러와서 가우시안 블러 & 캐니 엣지 검출을 100번 수행하도록 하였고, 그 실행 시간을 측정하여 출력했습니다.

#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;
	}
	
	cout << "Running GaussianBlur & Canny on 512x512 lenna image (100 times): " << endl;

	int64 t1 = getTickCount();

	Mat blurred, dst;
	for (int i = 0; i < 100; i++) {
		GaussianBlur(src, blurred, Size(), 1.0, 1.0);
		Canny(blurred, dst, 50, 150);
		cout << ".";
	}

	int64 t2 = getTickCount();

	cout << "\nIt took " << (t2 - t1) * 1000 / getTickFrequency() << " ms." << endl;

	return 0;
}


그 결과 OpenCV 3.2 버전을 사용하여 빌드했을 때에는 결과가 아래와 같구요..


OpenCV 3.3.0-rc 버전을 사용하여 빌드했을 때에는 결과가 이렇습니다.


미세하지만 3.3.0-rc 버전이 더 빠르게 동작하는 것 같습니다. OpenCV 3.3.0-rc 버전은 220~230ms 정도 걸리는데, OpenCV 3.2 버전은 240~260ms 정도로 분포하고 있네요. 좀 더 많은 함수를 사용해서 테스트를 해보면 좋겠지만, 일단은 이 정도만..



Posted by kkokkal
:

작년 4월인가에 라즈베리파이3B 모델을 사고, 라즈베리파이 전용 카메라 모듈도 구입을 했습니다. 이때만해도 8M 카메라 모듈이 나오기 전이라 5M 모듈만 있을 때였죠. 이거 사자마자 거의 같은 가격으로 8M 모듈이 발표되서 슬펐던 기억이 있는데.. 암튼 그때만해도 라즈베리파이에 카메라를 붙이고 OpenCV를 깔아서 뭐라도 해볼 요량이었지만, 어쩌다 보니 카메라를 사놓고 별것 해보지도 못하고 구석에 쳐박아 두었었네요.


이번에 다시 라즈비안 OS를 새로 깔고 새마음으로 라즈베리파이에 카메라를 붙였습니다. OpenCV는 이미 깔아놨고, 이번에는 라즈베리파이 카메라를 사용해보려고 합니다. 라즈베리파이카메라를 사용하기 위해 raspicam라는 이름의 라이브러리를 사용할 것입니다. raspicam 라이브러리에 대한 설명은 아래 링크를 참고합니다.

http://www.uco.es/investiga/grupos/ava/node/40


위 사이트에 쓰여있듯이 raspicam은 BSD 라이센스를 따르기 때문에 자유롭게 이용이 가능하고, 일반 C++ 인터페이스뿐만 아니라 OpenCV 인터페이스도 지원합니다. raspicam 라이브러리도 소스 코드를 다운받아서 직접 빌드를 진행해야 라이브러리 파일이 생성됩니다. 설치와 관련되어서는 아래 블로그 설명이 잘 되어 있네요.

http://webnautes.tistory.com/956


소스 코드 다운로드부터 빌드까지 명령어를 백업을 위해 아래에 정리해두겠습니다.

pi@GoPiGo:~ $ wget https://downloads.sourceforge.net/project/raspicam/raspicam-0.1.6.zip
pi@GoPiGo:~ $ unzip raspicam-0.1.6.zip
pi@GoPiGo:~ $ cd raspicam-0.1.6
pi@GoPiGo:~/raspicam-0.1.6 $ mkdir build && cd build
pi@GoPiGo:~/raspicam-0.1.6/build $ cmake .. 2>&1 | tee cmake_messages.txt


위와 같은 cmake 설정을 하고나면 화면에 출력되는 메시지가 cmake_messages.txt 파일에도 함께 저장됩니다. 이때 CREATE OPENCV MODULE=1 이라는 메시지가 출력이 되어야 raspicam 라이브러리가 OpenCV를 인식하고, OpenCV에서 함께 사용할 수 있도록 라이브러리를 생성합니다. cmake_messages.txt 파일의 전체 내용을 아래 [더보기]에 나타내었습니다.


cmake가 정상적으로 동작하였으면 이제 실제 빌드 작업을 수행합니다. 기본적으로 make -j2 명령을 입력하면 되고, 혹시나 하는 마음에 빌드 메시지도 함께 기록합니다. 빌드가 완료되면 sudo make install 명령으로 실제 라이브러리를 시스템 폴더에 복사합니다.

pi@GoPiGo:~/raspicam-0.1.6/build $ make -j2 2>&1 | tee build_messages.txt
pi@
GoPiGo:~/raspicam-0.1.6/build $ sudo make install
pi@GoPiGo:~/raspicam-0.1.6/build $ sudo ldconfig


위 사진은 sudo make install 명령을 입력했을 때의 모습입니다. 일단 raspicam 라이브러리 설치가 완료되었습니다. 참 쉽죠? :-)


그러면 이제 raspicam 라이브러리와 OpecCV 라이브러리를 이용하여 카메라 입력을 받고 간단한 얼굴 검출 프로그램을 만들어보겠습니다. 홈디렉토리 아래에 coding/opencv/facedetect 디렉토리를 만들고, 여기에 main.cpp 파일을 생성합니다. main.cpp 파일은 아래와 같이 작성합니다.

#include <opencv2/opencv.hpp>
#include <iostream>
#include <raspicam/raspicam_cv.h>

using namespace cv;
using namespace std;
 
int main(int argc, char* argv[]) {
	raspicam::RaspiCam_Cv cam;

	cam.set(CV_CAP_PROP_FORMAT, CV_8UC3);
	cam.set(CV_CAP_PROP_FRAME_WIDTH, 640);
	cam.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
	
	if (!cam.open()) {
		cerr << "Camera open failed!" << endl;
		return -1;
	}

	CascadeClassifier cascade("haarcascade_frontalface_default.xml");

	if (cascade.empty()) {
		cerr << "Failed to open xml file!" << endl;
		return -1;
	}

	Mat frame, gray, reduced;
	int64 t1, t2;
	bool do_flip = false;
	
	while (1) {
		cam.grab();
		cam.retrieve(frame);
		
		if (do_flip)
			flip(frame, frame, -1);

		t1 = getTickCount();
		
		cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
		resize(gray, reduced, Size(0, 0), 0.5, 0.5);
		
		vector<Rect> faces;
		cascade.detectMultiScale(reduced, faces, 1.1, 3, 0, Size(40, 40));
		
		for (size_t i = 0; i < faces.size(); i++) {
			Rect rc;
			rc.x = faces[i].x << 1;
			rc.y = faces[i].y << 1;
			rc.width = faces[i].width << 1;
			rc.height = faces[i].height << 1;
			
			rectangle(frame, rc, Scalar(0, 0, 255), 3);
		}
		
		t2 = getTickCount();
		cout << "It took " << (t2 - t1) * 1000 / getTickFrequency() << " ms." << endl;

		imshow("frame", frame);
		
		int k = waitKey(1);
		if (k == 27)
			break;
		else if (k == 'f' || k == 'F')
			do_flip = !do_flip;
	}

	cam.release();
	destroyAllWindows();
}


소스 코드가 그리 길지는 않죠? 일단 raspicam::RaspiCam_Cv 객체를 생성해서 카메라를 열고, 매 프레임마다 Haar Cascade Classifier로 얼굴을 검출합니다. 속도 향상을 위해서 매 프레임을 가로, 세로 1/2 크기로 줄인 다음에 얼굴을 검출하고, 검출된 얼굴 영역을 화면에 보여줄 때 다시 좌표를 2배 확대합니다. 제가 라즈베리파이에 카메라를 거꾸로 달아놔서 'f' 키를 누르면 영상을 flip 하여 얼굴 검출을 수행합니다.


Makefile은 아래와 같이 수정합니다.

CC = g++
CFLAGS = -g -Wall
SRCS = main.cpp
PROG = $(notdir $(CURDIR))

OPENCV = `pkg-config opencv --cflags --libs`
LASPICAM = -lraspicam -lraspicam_cv
LIBS = $(OPENCV) $(LASPICAM)

.PHONY: all clean

$(PROG):$(SRCS)
    $(CC) $(CFLAGS) -o $(PROG) $(SRCS) $(LIBS)

all: $(PROG)

clean:
    rm -f $(OBJS) $(PROG)


이제 터미널 창에서 make 명령을 입력하면 프로그램을 빌드하여 facedetect라는 실행 파일을 생성합니다.

위에서 haarcascade_frontalface_default.xml 파일은 OpenCV를 설치할 때 /usr/local/share/OpenCV/haarcascades 디렉토리에 만들어집니다. 그러므로 cp /usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml . 명령으로 현재 폴더로 복사하면 됩니다.


이제 터미널 창에서 ./facedetect 명령으로 프로그램을 실행하면 아래처럼 얼굴을 검출합니다.


왼쪽 상단에 나타난 창은 htop 프로그램인데요, 4개의 코어가 다 동작하는 것을 확인할 수가 있구요... 한 프레임에서 얼굴을 찾는데 대략 130~200 ms 정도의 시간이 걸리는 것을 확인할 수 있습니다.


약간의 속도 향상을 위해서 소스 코드에서 cascade.detectMultiScale(reduced, faces, 1.1, 3, 0, Size(40, 40)); 부분을 cascade.detectMultiScale(reduced, faces, 1.2, 3, 0, Size(60, 60), Size(240, 240)); 형태로 수정하고 프로그램을 다시 돌려보니 조금 빨라졌네요. :-)


Posted by kkokkal
:

소리 소문도 없이 OpenCV 3.3.0-rc 버전이 릴리즈되었습니다. OpenCV github releases 페이지를 보니 3일 전에 OpenCV 3.3.0-rc 버전이 소스 파일 형태로 업데이트가 되었다고 표시되어 있는데요, opencv_contrib 쪽 소스 코드의 3.3.0-rc 버전은 10일전에 올라왔다고 되어 있습니다. 아마도 2017년 6월 30일 경에 3.3.0-rc 버전이 모두 릴리즈되고 메인 소스 쪽에만 약간의 업데이트가 있었던 것은 아닌가 싶습니다. OpenCV 3.3.0-rc 버전은 아래 링크에서 다운로드 받을 수 있습니다.



OpenCV 3.3.0-rc 버전 릴리즈 소식은 OpenCV 공식 사이트에서도 언급이 되어 있지 않습니다. 조용히 RC 버전을 릴리즈하고 내부적으로 테스트를 하고 있는 것이 아닌가 싶은데요, 어쨋든 새롭게 릴리즈된 버전이고 하니 다운로드 받아서 직접 빌드하는 방법을 알아보겠습니다.


기존에 OpenCV 3.2 버전을 빌드하는 방법은 아래 블로그와 유투브에서 설명한 적이 있습니다. 혹시 OpenCV 빌드를 한 번도 안해보신 분들은 아래 글과 동영상을 먼저 훑어보시는 것을 권장하구요..



그럼 본격적으로 OpenCV 3.3.0-rc 버전을 빌드하는 방법을 설명하겠습니다.


개인적으로 OpenCV 빌드 작업은 C:\opencv 폴더를 만들어서 진행을 합니다. 그러므로 C:\opencv 폴더를 만들고, 여기에 OpenCV 3.3.0-rc 소스 코드의 압축 파일을 해제합니다. opencv 메인 소스와 opencv_contrib 소스 코드를 모두 압축 해제하면 아래와 같은 폴더 구조를 가지게 됩니다.


위 그림에서 mybuild 폴더는 실제 빌드 작업을 진행할 폴더이며, 여러분이 직접 만들어 주어야 합니다. 일단 폴더 구조를 위와 같이 구성하였으면 이제 CMake 프로그램을 실행하여 Visual Studio 2017 용 솔루션 파일과 프로젝트 파일을 생성합니다. CMake 사용법에 대한 자세한 설명은 위에 링크해놓은 블로그와 동영상을 참고하시기 바라며, 다만 여기서는 CMake 기본 설정에서 변경한 내역만 정리하겠습니다.


  • BUILD_EXAMPLES: 선택
  • BUILD_opencv_world: 선택
  • INSTALL_PYTHON_EXAMPLES: 선택
  • OPENCV_EXTRA_MODULES_PATH: C:/opencv/opencv_contrib-3.3.0-rc/modules
  • WITH_CUDA: 선택 해제
  • WITH_OPENGL: 선택


OpenCV 3.2에서는 opencv_contrib 쪽 소스 코드를 함께 빌드할 때 BUILD_opencv_world 옵션을 선택하면 에러가 발생하는 버그가 있었는데요, 그런 버그는 이미 예전에 해결이 되었습니다. 그리고 2017년 1월에 발생한 OpenCV 커밋 중에 opencv_contrib 모듈도 opencv_world 쪽으로 포함시키는 내용이 있어서 모든 opencv 기능을 opencv_world330.dll 하나로 사용할 수 있습니다. WITH_CUDA 선택을 해제한 이유는 CUDA가 Visual Studio 2017을 지원하지 않기 때문입니다.


위와 같이 설정하여 OpenCV.sln 파일을 생성합니다. 그리고 Visual Studio 2017에서 OpenCV.sln 파일을 불러와서 빌드를 진행하면 되는데요... 에러가 하나 발생하네요 ㅠㅠ


C:\opencv\opencv_contrib-3.3.0-rc\modules\ximgproc\src\structured_edge_detection.cpp 파일 584라인과 585 라인에서 M_PI를 사용하는 부분에서 에러가 발생하는데요, 아마도 math.h 파일의 M_PI를 제대로 포함하지 않았기 때문인 것 같습니다. 굳이 opencv 소스 코드에서 M_PI를 사용하는 것보다는 CV_PI를 사용하는 것이 더 깔끔할테니까 아래 그림과 같이 M_PI 대신 CV_PI로 소스 코드를 수정합니다.


그리고는 다시 빌드를 하면 잘 진행이 됩니다. (참 쉽죠? :-)


전체 솔루션 빌드를 진행하고, INSTALL 프로젝트도 따로 빌드를 하고나면 C:\opencv\mybuild\install 폴더에 헤더 파일, LIB 파일, DLL 파일이 사이좋게 모이게 됩니다.


opencv_world330.dll 파일 하나의 크기가 거의 100MByte입니다. 용량이 좀 부담스러울 수도 있지만 OpenCV 공부를 하는 과정에서는 opencv_world330.dll 파일 하나만 있으면 편해서 저는 opencv_world 속성을 선택하는 것을 선호합니다. 회사에서 프로젝트를 진행하거나 배포를 위한 목적이라면 개별 모듈을 따로 빌드하는 것이 더 좋겠지요.


참고로 OpenCV 3.3.0-rc 버전에서는 예전에 opencv_contrib 쪽 소스 구조에 있던 dnn(deep neural network) 모듈이 opencv 메인 소스 쪽으로 이동을 했습니다. 그 외에도 C++11 지원이 추가된 것으로 보이고, CPU 아키텍쳐(SSE, AVX, SIMD, etc)에 대한 소스 코드 분기가 많이 추가된 것 같네요. 공식적인 change log가 없어서 어떤 것이 더 바뀐 것인지는, 나중에 OpenCV 3.3.0 정식 버전이 릴리즈되면 알 수 있을 것 같습니다.







Posted by kkokkal
:

라즈베리파이에 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 $


여기에서 vi main.cpp 명령을 입력해서 아래와 같이 소스 코드를 입력합니다.


이번에는 Makefile을 생성하고, 아래와 같이 내용을 입력합니다.

CC = g++
CFLAGS = -g -Wall
SRCS = main.cpp
PROG = $(notdir $(CURDIR))

OPENCV = `pkg-config opencv --cflags --libs`
LIBS = $(OPENCV)

.PHONY: all clean

$(PROG):$(SRCS)
    $(CC) $(CFLAGS) -o $(PROG) $(SRCS) $(LIBS)

all: $(PROG)

clean:
    rm -f $(OBJS) $(PROG)

** 위에서 들여쓰기 되어 있는 부분은 TAB을 사용해야 합니다. **


이 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 정도로 측정이 되었습니다.



Posted by kkokkal
:

라즈베리파이에서 OpenCV 3.2를 설치하는 방법을 정리해보겠습니다. 라즈베리파이에 OpenCV를 설치한다는 것은 OpenCV 소스 코드를 직접 빌드하여 헤더 파일을 복사하고 OpenCV 라이브러리를 생성하는 작업을 의미합니다. 과정이 좀 길지만 차근차근 알아보겠습니다.


OpenCV 소스 코드를 빌드하려면 빌드 관련 도구나 필요한 라이브러리 패키지를 라즈베리파이에 미리 설치해두어야 합니다. 예를 들어, 정지 영상 포맷과 관련된 jpeg 라이브러리나 png 라이브러리, 비디오 파일 포맷 또는 스트리밍 관련 라이브러리 같은 것들을 미리 설치해야 정상적으로 빌드됩니다.


[빌드 관련 도구 설치] 실제 빌드 작업에 앞서 OpenCV 빌드에 필요한 패키지를 설치합니다.

pi@RaspberryPi3:~ $ sudo apt-get install build-essential cmake pkg-config


[정지 영상 파일 입출력]

pi@RaspberryPi3:~ $ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev


[비디오 파일 입출력/스트리밍]

pi@RaspberryPi3:~ $ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev
pi@RaspberryPi3:~ $ sudo apt-get install libxvidcore-dev libx264-dev libxine2-dev
pi@RaspberryPi3:~ $ sudo apt-get install libv4l-dev v4l-utils
pi@RaspberryPi3:~ $ sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev


[GUI] OpenCV의 highgui 모듈에서 GTK를 사용하도록 합니다.

pi@RaspberryPi3:~ $ sudo apt-get install libgtk2.0-dev


[기타/최적화]

pi@RaspberryPi3:~ $ sudo apt-get install libatlas-base-dev gfortran libeigen3-dev


[파이썬] OpenCV를 빌드한 후 C/C++ 뿐만 아니라 Python으로도 프로그래밍을 테스트하려고 합니다. 개인적으로는 Python 2.x 버전을 사용하지 않고 Python 3.x 버전만 사용할 것이구요.. 이를 위해서 python3-dev 또는 python3-numpy 패키지가 필요한데, 얘네 둘은 이미 설치가 되어 있을 겁니다. (없으면 설치해야죠.)

pi@RaspberryPi3:~ $ sudo apt-get install python3-dev python3-numpy


[OpenCV 소스 코드 다운로드할 디렉토리 생성과 이동]

pi@RaspberryPi3:~ $ mkdir opencv && cd opencv


[OpenCV 3.2 소스 코드 다운로드 및 압축 해제]

pi@RaspberryPi3:~/opencv $ wget -O opencv-3.2.0.zip https://github.com/opencv/opencv/archive/3.2.0.zip
pi@RaspberryPi3:~/opencv $ unzip opencv-3.2.0.zip


[OpenCV 3.2 Extra 모듈 소스 코드 다운로드 및 압축 해제]

pi@RaspberryPi3:~/opencv $ wget -O opencv_contrib-3.2.0.zip https://github.com/opencv/opencv_contrib/archive/3.2.0.zip
pi@RaspberryPi3:~/opencv $ unzip opencv_contrib-3.2.0.zip


[빌드 작업을 위한 디렉토리 생성과 이동]

pi@RaspberryPi3:~/opencv $ mkdir build && cd build


[cmake 구성] 아래 명령어가 좀 긴데요, 대충 보면 예제 파일들을 생성하고, Python 2.x 말고 Python 3.x를 지원하도록 하는 등의 옵션을 지정합니다. Extra 모듈 소스 코드 위치를 지정하고, OpenCV 소스 코드 위치가 ../opencv-3.2.0/ 임을 명시합니다. 그리고 cmake가 동작하면서 나타나는 출력 메시지를 모두 cmake_messages.txt 파일에 기록합니다.

pi@RaspberryPi3:~/opencv/build/ $ cmake \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_WITH_DEBUG_INFO=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_EXAMPLES=ON \
-DBUILD_TESTS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_opencv_python2=OFF \
-DBUILD_opencv_python3=ON \
-DINSTALL_C_EXAMPLES=ON \
-DINSTALL_PYTHON_EXAMPLES=ON \
-DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-3.2.0/modules \
-DENABLE_NEON=ON \
-DWITH_LIBV4L=ON \
../opencv-3.2.0/ 2>&1 | tee cmake_messages.txt

참고로 cmake_message.txt 파일에 기록된 내용을 아래 [더보기]에 정리해두었습니다.


[빌드!!!] 이제 실제 빌드 작업을 진행합니다. 라즈베리파이3은 4개의 코어가 있지만, -j4 옵션을 주면 발열때문에 문제가 생길까봐 -j2 옵션으로 빌드를 진행합니다. 혹시라도 에러가 발생할까봐 컴파일 메시지는 build_messages.txt 파일에도 저장해둡니다. 빌드 작업은 2시간 넘게 걸렸던 것같고, 간간히 선풍기로 라즈베리파이 보드를 식히면서 진행했습니다.

pi@RaspberryPi3:~/opencv/build/ $ make -j2 2>&1 | tee build_messages.txt


[설치 및 설치 확인] 아래 명령어를 입력한 후 3.2.0 이 출력되면 정상적으로 설치가 된겁니다.

pi@RaspberryPi3:~/opencv/build/ $ sudo make install
pi@RaspberryPi3:~/opencv/build/ $ sudo ldconfig
pi@RaspberryPi3:~/opencv/build/ $ pkg-config --modversion opencv
3.2.0
pi@RaspberryPi3:~/opencv/build/ $ 


[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/ $


잘 되네요~ :-)




Posted by kkokkal
:

라즈베리파이에서 사용하는 공식 OS 라즈비안 Jessie는 Debian 리눅스 Jessie를 기반으로 라즈베리파이에 맞게끔 커스터마이징된 OS이기 때문에 어쨋든 리눅스입니다. 소스 컴파일도 리눅스답게 gcc 또는 g++을 사용하고, apt-get 같은 명령어를 이용하여 패키지를 설치하구요.


요즘의 리눅스는 GUI가 기본이고 GUI 환경의 파일관리자가 기본으로 제공되지만, 라즈베리파이를 서버처럼 사용하고 주로 putty 같은 터미널 프로그램으로 접속해서 관리하는 경우에는 전통적인 텍스트 환경에서 명령어 기반의 파일 관리를 (어쩔 수 없이) 해야하는 경우가 많습니다. cp, mv, rm, rmdir 같은 명령어를 사용해서 파일을 복사하고 옮기고 지우는 작업을 하는 건데요.. 이것도 익숙해지면 할만하기는 하지만 가끔은 좀 더 편한 인터페이스가 있으면 좋겠다는 생각이 드는건 어쩔 수 없습니다.


그래서 라즈베리파이에서 사용할 수 있는 텍스트 기반 GUI를 지원하는 파일 관리자를 사용하는 방법을 알아보려고 합니다. 제가 설치할 프로그램은 mc와 linm인데요, 먼저 mc부터 설치를 해보겠습니다.


mc는 Midnight Commander라는 이름의 파일 관리 프로그램이구요, https://midnight-commander.org/ 에서 자세한 정보를 얻을 수 있습니다. mc 설치는 apt-get 명령을 이용하여 쉽게 설치할 수 있습니다. 터미널 창에서 sudo apt-get install mc 라고 입력하면 됩니다.


설치가 끝나고 터미널 창에서 mc를 실행하면 다음과 같은 화면이 나타납니다.


화면 색깔이라던가 위에 파일 목록이 나타나고, 아래쪽에 명령어를 입력할 수 있는 콘솔이 나타난다는 등의 모양새가 예전 도스 시절의 norton commander와 거의 유사합니다.


그런데 저는 노턴 코맨더를 사용하던 쪽이 아니었습니다. 주로 mdir을 사용하던 사람이었는데요, 리눅스에서도 이런 대결 구도(?)가 재현되네요. Mdir의 리눅스 클론(?)이 바로 linm 입니다.


linm은 아마도 http://kldp.net/projects/mls 사이트에서 프로젝트가 관리되고 있었나봅니다만, 현재는 연결이 되지 않고 있구요, 다만 자세한 정보는 https://wiki.kldp.org/wiki.php/LinM 페이지에서 볼 수 있습니다. linm은 현재 Kyu-Ung Lee 님의 프로젝트 페이지에서 소스 코드와 *.deb 파일을 다운로드 받을 수 있습니다.

https://launchpad.net/~kyu419/+archive/ubuntu/ppa/+packages


저는 라즈베리파이에 linm을 설치할 것이기 때문에 위 페이지에서 linm - 0.8.1-1-0ubuntu12 항목 아래에 있는 linm_0.8.1-1-0ubuntu12_armhf.deb 파일을 다운로드 받았습니다. (https://launchpad.net/~kyu419/+archive/ubuntu/ppa/+files/linm_0.8.1-1-0ubuntu12_armhf.deb) 그리고 이 파일을 FTP 프로그램을 이용하여 제 라즈베리파이로 옮겼습니다. 그리고 putty 프로그램으로 라즈베리파이에 접속해서 sudo dpkg --install linm_0.8.1-1-0ubuntu12_armhf.deb 명령을 입력하여 설치를 진행했습니다. (위에 위키 페이지에서는 zlib1g, openssl, libncurses, libncursesw5, libsmbclient 같은 패키지를 미리 설치해야 한다고 설명이 되어 있습니다만, 라즈베리파이에서 libncurses 같은 패키지가 잘 설치가 안되기도 하고, 또 굳이 얘네들 패키지를 설치하지 않고 곧바로 linm_0.8.1-1-0ubuntu12_armhf.deb 파일을 설치해도 잘 설치가 되더군요.)



설치가 끝나고 터미널 창에서 linm을 입력하면 아래와 같은 화면이 나타납니다.


화면 구성이나 색깔이 예전 도스의 mdir과 똑같습니다. 뭔가 아련한 느낌까지 들 정도네요. ㅎㅎ putty에서 linm을 실행하면 처음에 세로 줄이나 가로줄이 좀 깨지는 경우가 있는데, ALT+L 키를 눌러서 라인 코드를 바꿔주니까 깔끔하게 잘 나타납니다. (또는 F12를 눌러서 옵션 메뉴 아래 라인 코드 바꾸기를 선택하세요.) 화면을 분할하려면 Ctrl+W 키를 눌러주면 됩니다. 프로그램을 종료하려면 Ctrl+Q를 누릅니다.


개인적으로는 linm의 모양새가 더 친근해서 mc 보다는 linm을 사용합니다. 근데 linm은 화살표로 파일간 이동을 할 때 비정상적으로 비프음을 내는 경우가 많습니다. 근까 아래 화살표를 길게 누르다보면 맨 마지막 파일에 다다랐을 때 '딩~' 하는 소리가 나는 것은 그러려니한데, 보통 파일 이동 중간쯤에서도 '딩~' 소리가 나는 경우가 많아서, 뭔가 이상한 느낌을 주게 합니다. (putty의 문제인지...) mc는 그런 오동작이 없고, 또 메뉴 선택이나 파일 선택을 마우스를 이용해서 할 수도 있다는 장점이 있긴 하네요.



Posted by kkokkal
: