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 ]

Quadrotor20152015. 8. 31. 20:19


오늘은 윙윙이를 변신시키는(다이어트?) 과정을 포스팅해보려 합니다~ 편안하게요 ㅋㅋ


음.. 갑자기 생각난건데 최근 밴드 혁오의 윙윙 이라는 노래가 음원차트 상위권에 랭크되어있던데.. 


비슷하네요 ㅋㅋ 저도 쿼드로터가 날 때 윙윙거려서 윙윙이라고 지었는데 ㅋㅋ


어쨌든! 경량화 해야지 해야지 하면서 미루다가 이제서야 하네요.. ㅜ


먼저 다이어트 전 윙윙이입니다.



프롭가드 빼니까 좀 허술해보네요 ㅋㅋㅋ 물에 빠진 강아지마냥..


이왕 하는김에 어느 파츠가 몇 그램인지 측정하기위해 완전 분해를 결심했습니다~!


(그래놓고 측정한거 써놨던 종이 잃어버림 ㅜㅜ)


완전 산산조각났을 때는 정신이 없어서 사진을 못찍었네요 ㅠㅠ 


작업중에 건진 사진은 달랑 이거 하나..




프레임이 무거울줄 알았는데 오히려 모터가 꽤 무겁더라구요..


무게를 1/3정도 줄이는걸 목표로 삼았는데 무리라는 생각이 들었습니다.ㅜㅜ



아두이노 배선이 지저분하죠? 


직접 PCB를 뜨지않는 이상 전선은 어쩔 수 없다고 생각하고.. 최대한 무게를 줄여보자는 마음에!


전선은 좀 더 얇고 가벼운 걸로 싹 교체하고! 


저 검은 소켓을 비롯해 전원소켓, USB소켓까지 필요없는건 다 없애버렸습니다.




USB소켓은 프롭가드랑 닿아서 연결이 힘들길래 아예 선으로 빼서 늘어뜨려 놨어요~!


음.. 지금보니 무식하게 선을 납땜해놨는데.. 


전자과나 고수분들이 보시면 욕할지도 모르겠네요ㅜㅜ





아크릴판으로 층을 만들어서 따로 장착했던 센서도 한 층에 몰아넣었습니다ㅋㅋ


이왕 하는거 스펀지+양면테이프로 방진 효과도 노려 보고!


프롭가드도 프롭에 닿을랑 말랑해서 불안했는데


새로 만들어서 안쪽을 칼로 도려냈습니다~! 무게도 줄일겸 ㅋㅋㅋ




짠~! 진짜 뭔가 새로워진 것 같아서 개발 의욕도 솟더라구요


무거움 -> 더 많은 추력 필요 -> 더 많은 모터 회전 필요 -> 더 많은 진동 -> 센서로 전달


이런 식일까봐 무게를 줄여봤는데 잘한 것 같네요


줄인김에 +콥터에서 x콥터로 바꾸니까 자세제어도 더 잘되고..


컴퓨터 폴더 살펴보다가 사진이 보이길래 지나가는 포스팅을 해봤습니다~


기술적인 부분은 다음 포스팅에..






Posted by 너를위한노래

댓글을 달아 주세요

  1. 쿼드제작초보

    PID값을 잡는중인데 중심을 잡긴잡는데 정확히 잡지 못하고
    평형상태에서 -10~10사이로 왔다갔다하는 현상이 일어나고있습니다.
    쓰로틀이 커질수록 그런 현상이 더심하게 나타나는데.

    혹시 이런 문제점의 해결방법을 알고 계신지요.
    방진은 방진보드를 새로 구매하였고 귀마개를 이용하여 방진을 최대로 하여 효과를 봤습니다.
    모터와 프롭의 벨런스도 잘 맞추었구요.
    실험을 할때는 지면에서1.5m이상 공간에서 실험을 하엿습니다.

    혹시 제작할때 저와같은 문제가 있으셧다면 이문제를 어떻게 해결해야할까요?

    2015.09.01 19:51 [ ADDR : EDIT/ DEL : REPLY ]
    • 왔다 갔다 빠르게 반복된다면 PID제어량, PID게인을 점검해봐야 할 것 같구요, 천천히 기울어진다면 센서 각도를 점검해봐야할 것 같네요.. 전 두가지 문제를 번갈아서 모두 겪어봤어요 ㅠ

      2015.09.03 00:06 신고 [ ADDR : EDIT/ DEL ]
  2. 와 프롭가드 멋지네요. 어디서 구매하셨나요? 자작이라기엔 완성도 짱이네요!

    2016.01.23 06:34 [ ADDR : EDIT/ DEL : REPLY ]
  3. 쿼드콥터맨

    안녕하세요~!!! 저희도 이번에 졸업작품으로 아두이노 쿼드콥터랑 제어 어플 개발하고 있는데요 ㅠ 지금 완전 막혀있는 상태입니다.
    우선 MPU6050의 DMP?를 쓰고 있는데 이걸론 무리일까요? 샘플주기가 10ms정도 나오더라구요.. 100hz라는건데 노래님 포스트 보다보니 100hz론 택도 없다고 하셔가지고.. 멘붕입니다.. 처음부터 다시 짜야될지..

    그리고 모터 출력함수는 뭘 사용하셨나요? writemicroseconds는 헤더파일에서 듀티사이클값을 400hz이상으로 설정해놔도 167hz가 한계라고 하던데.. 오실로스코프가 없어서 확인을 못해보겠네요... 혹시 어떤 함수를 사용하셨는지요...

    아 그리고 PID제어는 단순히 각에대한 제어만 하신건가요? 저는 각에 대해 먼저 P제어를 하고 난 다음에 그 값을 목표각속도로 하여 각속도에 대한 PID제어를 한번 더 하는 이중 PID제어 알고리즘을 사용중인데, 어떤 알고리즘을 쓰시는지 궁금합니다!

    또 저희가 블루투스 통신으로(HC-06모듈) 제어를 하는데 이게 가끔 값이 튀어서 갑자기 곤두박질 치는 경우가 있더라구요.. 원래 블루투스가 이런건지 궁금합니다..

    그리고 프롭가드는 기성품을 사신건가요??? 완전 멋지네요.. 우리도 저런거 있었으면 프로펠러 안뿌러뜨리고, 뿌러질 걱정없이 팍팍 띄워볼텐데!! 발표가 당장 몇일 앞이라 주문할 엄두도 안나네요.

    질문이 좀 많은데ㅠ 답변 부탁드리겠습니다!!

    2016.04.12 01:56 [ ADDR : EDIT/ DEL : REPLY ]
    • 메일 보내신 분이시죠? 해당 내용 답글로 남깁니다.
      1. DMP
      MPU6050의 DMP는 내부에서 각도를 알아서 계산해주는 걸로 알고 있는데 맞나요?? 그게 10ms로 되어있다면 사용 불가능할 것 같습니다. 저도 100hz짜리 비싼 센서 썼었는데 택도 없더라구요

      2. PWM
      어떤 아두이노를 사용하시는지 모르겠지만, 저는 아둥이노2560의 pwm출력 단자를 사용했습니다. 각 출력 단자는 타이머와 연결되어있는데요, 공식 홈피에 가시면 몇번 단자가 어떤 타이머에 연결되어있는지 나와있을 겁니다. 각 타이머마다 주파수가 같지 않으니까 타이머 주파수 조절하는 함수를 사용하셔야 합니다. (TCCR1B=0x0A; 이런식으로 조절했었습니다.)

      3. 제어
      저도 이중 PID제어를 사용했구요, 제 블로그의 영상은 각도 PI + 각속도PD제어였습니다

      4. 블루투스
      저도 블루투스 쓰다가 어느순간 값이 누락되고 지연되고 이런 문제점이 많아서 WiFi로 갈아탔는데요, 블루투스를 계속 쓰실 거라면 초당 데이터 전송 횟수를 좀 줄여보시길 바랍니다. 저 같은 경우는 빨리 제어하고 싶어서 빨리 전송하다보면 입력 버퍼(?)같은데 쌓여서 밀리는건지 잘 안되더라구요

      5. 프롭가드
      2년전에 쿼드콥터 대회 나갈때 몇개 여분으로 샀던 건데요, 얼마 전 프롭가드 말고 프레임을 사려고 쇼핑몰에 문의해보니 지금은 프레임, 프롭가드 모두 안판다고 하시네요.
      프롭가드 있다고 프로펠러가 안부러지진 않구요ㅋㅋ 프로펠러 회전반경을 눈으로 볼 수 있어서 조심할 수 있는 정도입니다

      생각 나는대로 적어서 두서가 없네요 ㅎㅎ 발표 잘 하시길 바랍니다~!

      2016.04.27 14:38 신고 [ ADDR : EDIT/ DEL ]
  4. 드론초보

    와...딱 제가 하려는 부품들로 하려는 작업이에요.....
    혹시 소프트웨어는 어떤거 쓰셨나요???
    저는 multiwii 2.4로 하고있습니다.

    2019.01.21 19:37 [ ADDR : EDIT/ DEL : REPLY ]

Quadrotor20152015. 7. 24. 23:55

포스팅이 뜸한 사이 윙윙이(쿼드로터)에 많은 변화가 있었습니다~


점프선으로 복잡하게 얽혀있던 선을 모두 자르고 컴팩트하게 납땜해서 보기좋고 가볍게 해놨고, 센서에 방진장치로 양면테이프+스펀지를 대서 방진효과를 기대할 수 있게 해놨고, 불량 모터 교체, 라즈베리파이에서 오드로이드C1로 개선, 개발환경 구축, 시리얼 통신 비용 감소, +콥터에서 x콥터로 변경, 조종 어플 개선 등등 많이도 했네요.


그리고 그 동안은 게인값 튜닝에 많은 시간 투자를 했었는데.. 홧김에 제어기를 추가하니까 확실히 성능이 개선됐습니다.


아래 영상은 수동 조종 모드로 호버링을 시도한 영상입니다.



고도는 80cm로 고정시켜 놓았고 tack-off 버튼과 landing버튼으로 이륙과 착륙을 할 수 있게 해봤습니다. yaw각도 고정입니다.


이제 시작이네요! 이걸로 뭘 하느냐가 중요한 것 같습니다.


부셔먹지 말고 조심히 잘 해야지..


------------------------------------------------- 2015.07.29 추가 -------------

위 영상의 사용된 하드웨어는 아두이노Mega2560 + 오드로이드C1 + 갤럭시s4입니다. 오드로이드 운영체제는 RTOS가 아닌 하드커널에서 제공하는 우분투를 사용했고, 갤럭시s4는 안드로이드 KitKat(4.4.2)입니다. 

무선통신은 Wifi를 사용해 UDP통신을 하는 중이고(가끔 딜레이가 생기던데 원인 파악중..), 안드로이드 쪽에서 핫스팟을 켜두면 오드로이드에서 붙는 방식을 취하고 있습니다~







Posted by 너를위한노래

댓글을 달아 주세요

  1. 라임맛케익

    가속도, 자이로 센서값을 오일러각으로 변환-1을 보고 예전 상보필터설계 부분을 봤는데요 상보필터에 사용되는 acc이나 gyro 값들은 각각 가속도를 변화하여 만든 오일러각과 자이로값을 변화하여 만든 오일러각인것 맞나요? 그리고 '가속도, 자이로 센서값을 오일러각으로 변환-2'를 보고 싶은데 혹시 올려주실수 있나요?ㅠㅠ

    2015.07.25 16:21 [ ADDR : EDIT/ DEL : REPLY ]
    • 네 각각의 오일러각이 맞습니다~ 2편은.. 상보필터에대한 내용인데요 현재 작성중입니다.ㅜ 급하시면 예전에 썼던 상보필터 내용을 참고하시면 될거같아요~ 비슷한 내용입니다.

      2015.07.26 14:49 신고 [ ADDR : EDIT/ DEL ]
  2. 쿼드콥터

    통신을 사용하신거 같은경우에 블루투스 통신을 이용해서 조종하시고 계신건가요?

    2015.07.28 14:38 [ ADDR : EDIT/ DEL : REPLY ]
  3. 비밀댓글입니다

    2015.08.13 21:30 [ ADDR : EDIT/ DEL : REPLY ]
  4. 제이기를 추가하셨다고 했는데 구체적으로 어떻게 무엇을 추가해주셨는지 설명 부탁해도 될까요?? ^^

    2015.08.26 11:22 신고 [ ADDR : EDIT/ DEL : REPLY ]
  5. 프롭가드는어떻게구매하셨아요?

    2015.09.03 22:18 [ ADDR : EDIT/ DEL : REPLY ]
  6. 비밀댓글입니다

    2016.03.30 20:51 [ ADDR : EDIT/ DEL : REPLY ]
  7. 비밀댓글입니다

    2016.08.18 13:21 [ ADDR : EDIT/ DEL : REPLY ]
    • 먼저 위 글의 영상은 optical flow를 사용하지 않은 영상인 점 알아두시구요, 이 후에 올렸던 호버링 영상을 기준으로 말씀드리겠습니다. optical flow 센서(e.g. px4flow)는 사용하지 않았고 일반 모노카메라를 사용했습니다. 모노카메라로 optical flow를 통해 속도를 추정하고 이를 가속도, 자이로, 초음파 센서의 도움을 받아 실제 m/s의 속도를 구했었습니다. 말씀하신 것처럼 단순히 optical flow만으로는 호버링이 어렵습니다. 노이즈도 심하고 기체의 회전운동과 병진운동을 구분하기도 힘드니까요..

      2016.08.18 23:07 신고 [ ADDR : EDIT/ DEL ]
    • 비밀댓글입니다

      2016.08.24 13:20 [ ADDR : EDIT/ DEL ]