Computer Vision2015. 9. 25. 20:05


옵티컬 플로우는 컴퓨터비전을 공부하다 보면 꼭 나오는 주제입니다. 원리와 수식은 위키피디아, 블로그, openCV API에 많이 나와있으니 글 하단에
참고사이트로 대신하고, 이 포스팅에서는 제가 헷갈렸던 이야기와 몇 가지 개념에 대해 써보겠습니다.


옵티컬 플로우 또는 광류라고 하는 이 알고리즘은 간단히 말하면 차영상의 진화버전이라고 할 수 있겠습니다. 이전 프레임과 현재 프레임의 차이에 관심을 둔다는 점에서요.


저는 옵티컬 플로우를 처음에 아래 그림처럼 접했었습니다. 제 선배가 옵티컬 플로우를 사용해서 논문을 쓰는걸 봤는데 아래 그림과 같은 방식으로 사용하시더라구요.




이전 프레임에서 강인해 보이는(다음 프레임에서도 추출될 만한) 특징점 추출 후 현재 프레임에서 같은 특징점을 찾아 얼만큼 위치변화가 있었는지 보는 방식입니다.


여기서 짚고 넘어가야할 점은, 특징점의 분포가 움직이는 물체 부분에 밀집되어 있다는 점입니다. 위 그림처럼 카메라가 고정되어있고 자동차가 움직인다면 특징점은 차도에 많이 생기겠죠.


이렇다 보니 옵티컬 플로우를 객체 위치 인식 및 추적용으로 생각하시는 분들이 많은 것 같아요.(실제로 그렇게 사용하기도 합니다.)


하지만 제 생각에는 옵티컬 플로우는 물체가 어떻게 움직이고 있는지 판단할 때 가장 좋은 알고리즘이 아닐까 싶습니다. 


여기서 잠깐, Lucas-Kanade(LK), Horn-Schunk(HS)라는 키워드에 대해 짚고 넘어가겠습니다.


이것도 많이 헤매게 된 부분인데요, AR.Drone 논문에서 옵티컬 플로우를 LK와 HS를 모두 사용했다고 나오길래, 옵티컬 플로우는 크게 두 가지 방법이 있는 줄 알았습니다. openCV에는 아예 대놓고 calcOpticalFlowPyrLK()라는 함수가 있고 API를 봐도 루카스 카나데 방법을 사용한다고 써놨습니다. 근데 HS방법은 아무리 검색을 해봐도 안나와서 이상타 싶었는데 HS는 옵티컬 플로우를 어떻게 해석하는지에 중점을 두고 연구한 사람들이더라구요. (아래 참고사이트에 책 내용이 잘 나와 있다는 사이트를 참고하세요~)


위 자동차 그림처럼 특징점의 위치가 고르지 않은 상황에서는 HS방법을 쓰기 힘들 것 같네요.



            



이렇게 되어있는 경우 잘 들어맞을 것 같습니다.


객체와 배경이 함께 움직인다면 배경 부분까지 옵티컬 플로우가 만들어질 겁니다. 배경이 움직인다는건 다시 말해 카메라가 움직인다는 걸로도 볼 수 있기 때문에 배경의 속도는 카메라의 속도로 이어집니다.


이런 생각에 착안해 화면 전체의 옵티컬 플로우를 구하기 위해 찾아보았습니다.


아래의 제가 찍은 옵티컬플로우 동영상과 같이, 윙윙이에도 이런 방식을 적용했습니다.





openCV로 구현했구요, 프레임을 100개의 정사각형 블럭으로 나누고 블럭 중앙을 특징점으로 정한다음에 다음 프레임에서 특징점을 찾는 방식입니다.


노이즈가 심한거는 옵티컬 플로우 함수의 파라미터를 조정해서 개선했구요, 말도 안되게 튀는 노이즈는 if문으로 제거했습니다.


원래는 RANSAC을 이용해서 outlier 필터링을 하려고 했는데 각 벡터들을 평균해보니 꽤 쓸만한 값이 나와서 일단 그대로 사용하는 중입니다.


함수는 


calcOpticalFlowPyrLK(frame_prev, frame_gray, featurePrev, featureNext, isFound, err, winSize, 3, termcrit, 0, 0.01);


이렇게 사용중입니다.


frame_prev : 이전 프레임(8비트 단일 채널)

frame_gray : 현재 프레임(8비트 단일 채널)

featurePrev : 이전 프레임의 특징점 좌표들(vector<Point2f>)

featureNext : 현재 프레임의 특징점 좌표들(vector<Point2f>) - 함수 내부에서 만들어서 출력해줌(길이는 featurePrev와 동일)

isFound : 특징점을 찾는데 성공했는지 배열로 저장(길이는 featurePrev와 동일)

err : 이전 특징점과 현재 특징점간의 거리를 배열에 저장((길이는 featurePrev와 동일)

winsize : LK방법이므로 지역적으로 찾기위한 윈도우 크기(Size)

3 : 피라미드 최대 계층 개수

termcrit : 종료 조건(TermCriteria termcrit(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03); 이렇게 사용중)

0.01 : 최소 고유값


여기서 성능에 가장 영향을 많이 미치는 부분은 윈도우 크기와 피라미드 최대 계층 개수였습니다. 윈도우 크기를 늘리거나 계층 수를 늘리면 노이즈가 적어지고 성능이 좋아지지만 처리 속도가 느려져 실시간 피드백용으로는 적합하지 않았습니다.


위 동영상의 성능과 보정, 융합 결과는 다음 포스팅에서 다루기로 하고 오늘은 여기까지~!




참고 사이트 및 문헌

OpenCV-optical flow ( http://docs.opencv.org/master/d7/d8b/tutorial_py_lucas_kanade.html#gsc.tab=0 )

책의 내용과 이론 설명이 잘 되어있는 사이트( http://lueseypid.tistory.com/98 )

Determining optical flow - HornSchunk ( http://dspace.mit.edu/bitstream/handle/1721.1/6337/AIM-572.pdf?sequence=2 )

The navigation and control technology inside the ar. drone micro uav http://cas.ensmp.fr/~petit/papers/ifac11/PJB.pdf )






Posted by 너를위한노래

댓글을 달아 주세요

  1. 김지환

    글 정말 많이 도움되었습니다! 감사합니다. 한가지 질문이 있는데요, 100개로 나뉜 블럭의 중심을 특징으로 사용하셔서 다음 프레임에서 같은 특징을 찾으신다고 하시는데 어떤 특징을 사용하셨는지 알려주실 수 있으신가요?

    2016.05.27 22:28 [ ADDR : EDIT/ DEL : REPLY ]
    • 특징점을 고르는 것도 연산 부하가 걸려서 이 단계를 생략했습니다. 그냥 고정된 x, y 좌표 100개를 사용했습니다. 굳이 특징이라고 하면 픽셀의 그레이스케일 intensity를 사용했다고 해도 될까요 ㅋㅋ

      2016.08.24 20:42 신고 [ ADDR : EDIT/ DEL ]
  2. 광류

    궁금한 것이 있어 질문드립니다. 제가 optical flow를 써서 야구배트를 추적하려고 하는데요 배트의 속도가 빠른데 optical flow로 가능할까요?

    카메라는 고정 되어 있습니다. 야구배트의 체크스윙을 판별하려고 하는데 가능한지 알고 싶습니다. ㅠㅠ 도와주세요 ㅠㅠ

    2016.10.03 23:00 [ ADDR : EDIT/ DEL : REPLY ]

Linux2015. 6. 15. 21:40

http://karytech.blogspot.kr/2014/05/opencv-249-on-ubuntu-1404.html

OpenCV 2.4.9 was released on April 2014. See more here.

This is another post in a series of walkthroughs that will hopefully make your life easier to configure, compile, install and test it out.

The dependencies are divided into categories. I have only tested it with GTK.

If you don't need the latest OpenCV then you can easily install version 2.4 using apt:
sudo apt-get install libopencv-dev
If you wanna use the latest version, then follow the steps above:

Install Dependencies


Essentials
These are libraries and tools required by OpenCV.
sudo apt-get install build-essential checkinstall cmake pkg-config yasm

Image I/O
Libraries for reading and writing various image types. If you do not install then the versions supplied by OpenCV will be used.
sudo apt-get install libtiff4-dev libjpeg-dev libjasper-dev


Video I/O
You need some or all of these packages to add video capturing/encoding/decoding capabilities to the highgui module.
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev

Python
Packages needed to build the Python wrappers.
sudo apt-get install python-dev python-numpy

Other third-party libraries
Install Intel TBB to enable parallel code in OpenCV.
sudo apt-get install libtbb-dev

GUI
The default back-end for highgui in Linux is GTK. You can optionally install QT instead of GTK and later enable it in the configuration (see next section) but I haven't tested it with QT on Ubuntu 14.04 yet. 
sudo apt-get install libqt4-dev libgtk2.0-dev

Download Compile & Install

Get a copy of the source code here, extract and create a build directory:
unzip opencv-2.4.9.zip
cd opencv-2.4.9/
mkdir build
cd build
Configure using CMake. You have a lot of options in this step. This is what I use:
cmake -D WITH_XINE=ON -D WITH_OPENGL=ON -D WITH_TBB=ON -D BUILD_EXAMPLES=ON ..
If you add -D WITH_QT=ON, the highgui module will use QT instead of GTK. For more information on the options, look at the CMakeLists.txt file. When you are happy with the configuration you have, you can start compiling:
make
If compilation finishes without errors, you can install by saying:
sudo make install
Finally, make sure that your programs can link to the OpenCV library in run-time by adding the following line at the end of your /etc/ld.so.conf:
/usr/local/lib
And then configure dynamic linker run-time bindings:
sudo ldconfig

Testing

An easy way to test that the compilation went well is to use the OpenCV tests and samples. For example, go to opencv-2.4.9/build/bin and run:
./cpp-example-opencv_version
You should get the correct version.

If you run other tests notice that some failures come from missing image files. To correctly run these tests or samples you should move the corresponding image files from opencv-2.4.9/samples to OpenCV-2.4.9/build/bin.

For testing that you can compile your own programs and link against the installed OpenCV libraries I have packaged the face detection sample with all the necessary files and a simple Makefile. Download it here, extract and type:
make
This should compile and run with a test image, so you should see something like this:


'Linux' 카테고리의 다른 글

rc.local에 등록한 시작프로그램이 두번 실행되는 현상  (2) 2015.07.16
OpenCV 2.4.9 on Ubuntu 14.04  (0) 2015.06.15
Posted by 너를위한노래

댓글을 달아 주세요

Android2014. 11. 28. 16:10

이번에는 안드로이드 NDK개발환경 구축에 관해서 간단하게(스크린샷 없이) 포스팅 할건데요, 제 얕은 지식으로 이해한 바를 최대한 써보겠습니다. ㅜㅜ


개발환경 구축에 필요한 툴과 라이브러리는 다음과 같습니다.


JDK

JDK_7_51 - (http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html#jdk-7u51-oth-JPR)

환경변수 설정

이클립스

케플러 - (http://www.eclipse.org/downloads/packages/release/Kepler/SR2)

안드로이드 ADT설치 (help - install new software)

안드로이드

SDK - adt-bundle-windows-x86_64-20140321

안드로이드용 OpenCV

OpenCV-2.4.9-android-sdk

안드로이드 NDK

android-ndk-r10c-windows-x86_64


다운로드, 설치 방법과 경로 설정 등은 다른 블로그에 많이 나와있으니 생략하겠습니다.


모두 설치하셨다면, 프로젝트를 만들어야 할텐데요. 맨땅에다가 만들지 않고 예제를 수정하는 방법으로 만드려고 합니다.


OpenCV 예제 중 OpenCV Tutorial 2 - Mixed Processing 이라는 예제가 있을텐데요, 이 안에서는 CameraBridgeViewBase로 카메라를 다루지만 AutoFocus기능을 사용하기 까다롭더라구요 (Camera객체를 만들어서 start시키려고 하면 CameraBridgeViewBase와 충돌하는 듯 합니다). 하지만 NDK개발이 가능합니다.


그리고 OpenCV Tutorial 3 - Camera Control 이라는 예제는 CameraBridgeViewBase를 상속받은 JavaCameraView를 사용해서 카메라를 다루는데, 이 클래스 안에 mCamera가 Camera 객체이기 때문에 AutoFocus기능을 사용하기 수월합니다. 하지만 NDK개발 구축이 안되어있습니다.


이 두 예제를 합칠건데요, 일단 그냥 Tutorial 2 의 패키지를 지워버리고  Tutorial 3의 패키지를 가져오는 식으로 하셔도 됩니다. 


다만 두 프로젝트간에 다른건 조정 해줘야합니다. Menifest파일의 패키지와 액티비티 이름, 옮긴 후 액티비티의 onCreate에서 레이아웃 이름 등등은 알아서 조절하시길 바랍니다.


이렇게 해서 만들어진 프로젝트는 JavaCameraView의 mCamera를 이용한 AutoFocus가 가능하고, JavaCameraView의 onCameraFrame에서 OpenCV영상처리도 가능하며 onCameraFrame에서 native 함수를 호출함으로써 NDK 영상처리 개발도 가능합니다.




Tip : native 함수는 Java_com_abc_core_MainActivity_func() 처럼 생겼는데 맨 처음 Java는 고정이고 다음은 com.abc.core.MainActivity라는 액티비티의 func()함수로 사용하겠다는 의미입니다. 즉 위처럼 선언된 네이티브 함수는 com.abc.core.MainActivity 액티비티에 public native void func(); 이렇게 선언되어있어야 합니다. 오타가 나거나 경로가 틀리면 native 함수를 찾을 수 없다고 출력되며 앱이 종료됩니다.





Posted by 너를위한노래

댓글을 달아 주세요