Jetson 개발 보드에는 작은 5백만 화소 MIPI CSI-2 카메라가 탑재되어 있다. 이 카메라는 최대 2592x1944까지 지원하는 HD급 영상을 받아올 수 있다.

이 카메라를 통해 영상을 입력받는 방법을 알아보자.

특히 nvidia toolkit에 포함된 nsight 를 활용하여 로컬 머신에서 개발한 다음 jetson tx2보드(이하 타겟)에 전송하여 실행하는 방식을 사용하기로 한다.


이를 위해서는 로컬 머신과 타겟에 동일한 버전의 CUDA와 opencv가 설치되어 있어야 한다. 

여기서는 CUDA 8.0, opencv 3.3.1 버전을 기준으로 하였다.

Opencv를 설치하는 자세한 방법은 http://kyubot.tistory.com/93 을 참조하면 된다.

tx2에 opencv를 설치하는 방법은 인터넷에 자세히 나와있으므로 검색을 통해 설치한다.


로컬 머신에 프로젝트 생성하기


먼저 로컬 머신에서 nsight 를 실행하여 이름이 "simpleCapture"인 간단한 C++ 프로젝트를 생성한다.


 자동으로 CUDA Toolkit 8.0이 선택되어 있다.

Finish를 누르면 된다.

왼편 패널에서 새로 생성된 프로젝트에 마우스 커서를 올리고 우측 버튼을 누른다음 New --> Source Folder 를 선택하고 

Folder Name에 src라는 이름을 넣는다.


방금 생성된 폴더에서 다시 마우스 오른쪽 버튼을 눌러 New --> Source File 을 선택하고

Source file 이름에 main.cpp 라고 넣는다.



이렇게 하면 기본적으로 CUDA 관련 내용이 추가된 코드가 생성된다.

이제 이 코드를 모두 삭제하고 새로 작성한다.

과감하게 지우자...


이제 빈 파일에 다음 소스코드를 추가한다.

전체 코드를 텍스트로 올릴 수 있지만 간단한 코드이므로 코드가 어떻게 구성되었는지 알아보기 위해서 한자한자 입력해보는것을 권한다. 각 코드의 세부사항은 다음에 이어진다.



OPENCV 관련 라이브러리 추가하기


이대로 빌드하면 역시 빌드되지 않는데 그것은 아직 opencv 관련 헤더와 라이브러리가 적절하게 설정되지 않았기 때문이다.

어떤 헤더와 라이브러리가 설치되었는지 확인하기 위해 터미널을 열고 다음과 같이 입력해보자.


$ pkg-config --libs opencv

$ pkg-config --cflags opencv



이제 이 항목들을 각각 프로젝트의 include와 library항목에 넣어보자.


Include path에 /usr/local/include/opencv 항목과 /usr/local/include 를 추가하였다.


-l 항목에는 필요한 라이브러리를 추가하고 경로 설정 -L 에는 /usr/local/lib 를 추가한다.



이제 망치 모양의 빌드 버튼을 눌러 빌드가 정상적으로 진행되는지 확인한다.


make all 

Building target: simpleCapture

Invoking: NVCC Linker

/usr/local/cuda-8.0/bin/nvcc --cudart static -L/usr/local/lib --relocatable-device-code=false -link -o  "simpleCapture"  ./src/main.o   -lopencv_core -lopencv_video -lopencv_videoio -lopencv_flann -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui

nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).

Finished building target: simpleCapture



이제 실행 버튼을 누루면 아래와 같이 카메라가 실행되는 것을 확인할 수 있다.


타겟 TX2 보드에서 실행하기


이제 TX2개발보드에서도 동일하게 실행이 되도록 해보자.

이렇게 하기 위해서는 Remote 개발 환경을 추가해야한다. 현재 TX2 타겟과 로컬 머신은 아래와 같이 구성되어 있다.


이제 nsight 의 프로젝트에서 마우스 오른쪽 클릭하여 Property --> Build -> Target Systems에서 Manage를 눌러 타겟을 추가한다.

타겟의 ip와 username 여기서는 nvidia 를 입력한다.


 Project Path는 타겟에 만들어질 프로젝트 위치를 의미한다. 

Toolkit에 Manage를 눌러 cuda-8.0을 검색하여 추가한다. 

CPU 아키텍쳐는 AArch64 로 설정한다.


이제 빌드 환경을 방금 추가한 Remote 의  Debug로 설정한다.

여기서 다시 망치 버튼을 눌러 빌드를 하면 타겟의 보드에서 빌드가 수행된다.

이제 원격 환경에서 실행을 하기 위해 실행 환경을 아래와 같이 추가한다.


메뉴에서 Run --> Run As --> Remote C/C++ Application을 눌러 실행 환경을 추가한다.

    



타겟의 카메라 정보 설정하기


이렇게추가 되면 타겟에서 프로그램을 실행할 수 있다.

하지만 다음과 같은 에러가 뜨면서 실행이 되지 않을 것이다.


nvidia@tegra-ubuntu:~$ /bin/sh -c "cd \"/home/nvidia/workspace_remote/simpleCapture/Debug\";export LD_LIBRARY_PATH=\"/usr/local/cuda-8.0/lib64\":\${LD_LIBRARY_PATH};\"/home/nvidia/workspace_remote/simpleCapture/Debug/simpleCapture\"";exit

VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV

OpenCV Error: Unspecified error (GStreamer: unable to start pipeline

) in cvCaptureFromCAM_GStreamer, file /home/nvidia/opencv/modules/videoio/src/cap_gstreamer.cpp, line 881

VIDEOIO(cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L2, reinterpret_cast<char *>(index))): raised OpenCV exception:



빨간색으로 하이라이트된 부분이 원인이다. 이것은 TX2에 장착된 카메라가 지원하는 형식이 달라서 발생하는 것으로 TX2보드에 장착된 CSI 카메라를 사용하기 위해서는

정확한 입력 타입을 설정해주어야 한다.

다시 소스코드로 돌아가서 main 함수의 상단 VideoCapture 오브젝트 선언부분을 다음과 같이 변경한다.

먼저 string 변수를 하나 만들고 여기에 카메라 영상 입력에 관한 정보를 넣는다.

그리고 캡춰 스트림에 이 변수를 입력하면 끝.

int main()
{
	const string gst = "nvcamerasrc ! video/x-raw(memory:NVMM), width=(int)1180, height=(int)720, format=(string)I420, framerate=(fraction)24/1 ! nvvidconv flip-method=6 ! video/x-raw, format=(string)I420 ! videoconvert ! video/x-raw, format=(string)BGR ! appsink";
	VideoCapture stream1(gst);   //0 is the id of video device.0 if you have only one camera.


이제 다시 실행버튼을 누르면 정상적으로 실행이 진행되는 것을 볼 수 있다.


nvidia@tegra-ubuntu:~$ /bin/sh -c "cd \"/home/nvidia/workspace_remote/simpleCapture/Debug\";export LD_LIBRARY_PATH=\"/usr/local/cuda-8.0/lib64\":\${LD_LIBRARY_PATH};\"/home/nvidia/workspace_remote/simpleCapture/Debug/simpleCapture\"";exit


Available Sensor modes :

2592 x 1944 FR=30.000000 CF=0x1109208a10 SensorModeType=4 CSIPixelBitDepth=10 DynPixelBitDepth=10

2592 x 1458 FR=30.000000 CF=0x1109208a10 SensorModeType=4 CSIPixelBitDepth=10 DynPixelBitDepth=10

1280 x 720 FR=120.000000 CF=0x1109208a10 SensorModeType=4 CSIPixelBitDepth=10 DynPixelBitDepth=10


NvCameraSrc: Trying To Set Default Camera Resolution. Selected sensorModeIndex = 1 WxH = 2592x1458 FrameRate = 30.000000 ...



(simpleCapture:2855): Gtk-WARNING **: cannot open display:

logout


실제로는 영상 장치를 원격으로 불러올 수 없기 때문에 원격에서 창을 열지 못한다. 

따라서 타겟에 직접 키보드와 모니터를 연결하고 실행파일이 있는 장소 (여기서는 ~/workspace_remote/simpleCapture/Debug )로 이동하여

$ ./simpleCapture 를 입력하여 실행한다. 

카메라 영상이 화면에 표시된다. 영상이 뒤집어진것에 주의


실행 결과를 보면 영상이 180 뒤집어진 상태로 보여지는 것을 확인할 수 있는데 이것은 cv::flip 함수를 통해 간단히 뒤집을 수 있다.

윈도우에 카메라 영상을 뿌려주는 imshow 와 스트림에서 읽어서 cameraFrame에 넣는 stream1.read(cameraFame) 사이에 cv:flip 으로 cameraFrame을 뒤집는 코드를 추가한다. 첫번째 인자는 출력, 두번째는 입력 프레임이고 세번째 인자는 뒤집는 축을 의미한다.

위아래만 뒤집으면 좌/우가 반대로 나오므로 다시 세로축으로 뒤집어야 된다. 

		Mat cameraFrame;
		stream1.read(cameraFrame);
		cv::flip(cameraFrame, cameraFrame, -1);			//Flip image about y axis(-1)
		cv::flip(cameraFrame, cameraFrame, 1);		//Flip image about x axis(-1)
		imshow("cam", cameraFrame); 


이제 Jetson Tx2 보드로부터 카메라 영상을 받아 여러가지 처리를 할 수 있게 된다.


2018/1/17에 최초 발행됨.


+ Recent posts