{"id":6855,"date":"2019-05-15T13:09:30","date_gmt":"2019-05-15T04:09:30","guid":{"rendered":"http:\/\/www.gisdeveloper.co.kr\/?p=6855"},"modified":"2020-05-28T10:34:15","modified_gmt":"2020-05-28T01:34:15","slug":"python%ea%b3%bc-opencv-37-optical-flow","status":"publish","type":"post","link":"http:\/\/www.gisdeveloper.co.kr\/?p=6855","title":{"rendered":"Python\uacfc OpenCV \u2013 41 : Optical Flow"},"content":{"rendered":"<p>\uc774 \uae00\uc758 \uc6d0\ubb38\uc740 https:\/\/opencv-python-tutroals.readthedocs.io\/en\/latest\/py_tutorials\/py_video\/py_lucas_kanade\/py_lucas_kanade.html \uc785\ub2c8\ub2e4.<\/p>\n<p>\uc774 \uae00\uc5d0\uc11c\ub294 \uad11\ud559 \ud750\ub984(Optical Flow)\uc744 \uc774\ud574\ud558\uace0 Lucas-Kanade \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc774\ub97c \uc608\uce21\ud574 \ubcf4\ub294 \uc608\uc81c\ub97c \uc0b4\ud3b4\ubd05\ub2c8\ub2e4. OpenCv\uc5d0\uc11c\ub294 Lucas-Kanade \ubc29\ubc95\uc740 cv2.calcOpticalFlowPyrLK \ud568\uc218\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<p>\uba3c\uc800 Optical Flow\ub294 \uce74\uba54\ub77c \ub610\ub294 \ubb3c\uccb4\uc758 \uc774\ub3d9\uc5d0 \uc758\ud574 \uc0dd\uae30\ub294 \uc5f0\uc18d\ub41c 2\uac1c\uc758 \uc774\ubbf8\uc9c0 \uac04\uc758 \uc5b4\ub5a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ud328\ud134\uc785\ub2c8\ub2e4. \uc774 \uc774\ub3d9 \ud328\ud134\uc740 \uccab\ubc88\uc7ac \ud504\ub808\uc784\uc5d0\uc11c \ub450\ubc88\uc9f8 \ud504\ub808\uc784 \uac04\uc758 \uc5b4\ub5a4 \uc9c0\uc810\uc758 \uc774\ub3d9\uc744 \ubcf4\uc5ec\uc8fc\ub294 2\ucc28\uc6d0 \ubcc0\uc704 \ubca1\ud130(Displacement Vector)\uc785\ub2c8\ub2e4. \uc544\ub798 \uc774\ubbf8\uc9c0\ub97c \ubcf4\uba74..<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.gisdeveloper.co.kr\/wp-content\/uploads\/2019\/05\/optical_flow_basic1.jpg\" alt=\"\" width=\"437\" height=\"194\" class=\"aligncenter size-full wp-image-6856\" \/><\/p>\n<p>5\uac1c\uc758 \uc5f0\uc18d\ub41c \ud504\ub808\uc784\uc5d0\uc11c \ube68\uac04 \uacf5\uc774 \uc774\ub3d9\ud558\uace0 \uc788\ub294 \uadf8\ub9bc\uc785\ub2c8\ub2e4. \ud558\uc580\uc0c9 \ud654\uc0b4\ud45c\uac00 \ubc14\ub85c \ubcc0\uc704 \ubca1\ud130\uc785\ub2c8\ub2e4. Optical Flow\ub294 \ub2e4\uc591\ud55c \ubd84\uc57c\uc5d0\uc11c \ud65c\uc6a9\ub418\ub294\ub370, \ub2e4\uc74c\uacfc \uac19\uc740 \uc751\uc6a9 \ubd84\uc57c\uac00 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<ul>\n<li>\ubb3c\uccb4\uc758 \uc774\ub3d9 \ubd84\uc11d<\/li>\n<li>\ube44\ub514\uc624 \uc555\ucd95<\/li>\n<li>\ube44\ub514\uc624 \ud654\uc9c8 \uac1c\uc120<\/li>\n<li>\ub4f1\ub4f1<\/li>\n<\/ul>\n<p>Optical Flow\ub294 \uba87\uac00\uc9c0 \uac00\uc815\uc774 \uc788\uc73c\uba70, \uadf8\uc911 2\uac00\uc9c0\ub294 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<\/p>\n<ol>\n<li>\uac1d\uccb4\uc758 \ud53d\uc140 \uac15\ub3c4\ub294 \uc5f0\uc18d\ub41c \ud504\ub808\uc784 \uac04\uc5d0 \ubcc0\ud658\uc9c0 \uc54a\ub294\ub2e4.<\/li>\n<li>\ud55c \ud53d\uc140\uc758 \uc774\ub3d9\uacfc \uadf8 \uc778\uadfc \ud53d\uc140\uc758 \uc774\ub3d9\uc740 \uc720\uc0ac\ud558\ub2e4.<\/li>\n<\/ol>\n<p>\uc774\ub7ec\ud55c Optical Flow\ub97c \ubd84\uc11d\ud558\ub294 \ubc29\ubc95\uc73c\ub85c Lucas-Kanade \ub9e4\uc11c\ub4dc\uac00 \uc788\ub294\ub370, OpenCV\uc5d0\uc11c cv2.calcOpticalFlowPyrLK()\ub77c\ub294 \ud558\ub098\uc758 \ud568\uc218\ub97c \ud1b5\ud574 \uac00\ub2a5\ud569\ub2c8\ub2e4. \ube44\ub514\uc624\uc5d0\uc11c \uc5b4\ub5a4 \ud3ec\uc778\ud2b8\ub97c \ucd94\uc801\ud574 \ubcf4\ub294 \ud558\ub098\uc758 \uc608\uc81c\ub97c \uc0b4\ud3b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. \uc5b4\ub5a4 \ud3ec\uc778\ud2b8\uc5d0 \ub300\ud55c \uacb0\uc815\uc740 cv2.goodFeaturesToTrack() \ud568\uc218\ub97c \uc0ac\uc6a9\ud558\ub294\ub370, \uc774 \ud568\uc218\ub294 Shi-Tomasi \ubc29\uc2dd\uc5d0 \uc758\ud55c \ud2b9\uc9d5\uc810\uc73c\ub85c\uc368 \ucf54\ub108(Corenr)\ub97c \ucc3e\uc544\ub0c5\ub2c8\ub2e4. \uccab\ubc88\uc9f8 \ud504\ub808\uc784\uc5d0\uc11c \ucf54\ub108\ub97c \ucc3e\uc544\ub0b4\uc5b4 \ucd94\uc801\ud560 \ud3ec\uc778\ud2b8\ub85c \uacb0\uc815\ud569\ub2c8\ub2e4. \uadf8\ub9ac\uace0 \uc5f0\uc18d\ub41c 2\uac1c\uc758 \ud504\ub808\uc784\ub4e4 \uac04\uc5d0 Lucas-Kanade Optical Flow\ub97c \uc0ac\uc6a9\ud558\uc5ec \ubc18\ubcf5\uc801\uc73c\ub85c \ucd94\uc801\ud569\ub2c8\ub2e4. cv2.calcOpticalFlowPyrLK() \ud568\uc218\uc5d0 \uc774\uc804 \ud504\ub808\uc784, \ucd94\uc801\ud560 \uc774\uc804 \ud3ec\uc778\ud2b8, \ub2e4\uc74c \ud504\ub808\uc784 \ub4f1\uc744 \uc778\uc790\ub85c \uc804\ub2ec\ud568\uc73c\ub85c\uc368 \uc774\ub8e8\uc5b4\uc9d1\ub2c8\ub2e4. \uc774 \ud568\uc218\ub294 \uc774\uc804 \ud504\ub808\uc784\uc5d0\uc11c \ucd94\uc801\ud560 \ud3ec\uc778\ud2b8\uac00 \uc5f0\uc18d\ub41c \ub2e4\uc74c \ud504\ub808\uc784\uc5d0\uc11c \ucd94\uc801\ub420 \uacbd\uc6b0 \uc0c1\ud0dc\uac12 1\uc744 \ubc18\ud658\ud558\uace0 \ubc1c\uacac\ub418\uc9c0 \ubabb\ud560 \uacbd\uc6b0 0\uc744 \ubc18\ud658\ud569\ub2c8\ub2e4. \ub610\ud55c \ucd94\uc801\ud560 \ud3ec\uc778\ud2b8\uac00 \uc774\ub3d9\ud55c \uc0c8\ub85c\uc6b4 \uc704\uce58\uac12\ub3c4 \ud568\uaed8 \ubc18\ud658\ud569\ub2c8\ub2e4. \ub2e4\uc74c \uc608\uc81c\ub97c \ud1b5\ud574 \ub354 \uae4a\uc774 \uc774\ud574\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">\r\nimport numpy as np\r\nimport cv2\r\n\r\ncap = cv2.VideoCapture('.\/data\/vtest.avi')\r\n\r\n# params for ShiTomasi corner detection\r\nfeature_params = dict( maxCorners = 100,\r\n                       qualityLevel = 0.01,\r\n                       minDistance = 30,\r\n                       blockSize = 14)\r\n\r\n# Parameters for lucas kanade optical flow\r\nlk_params = dict( winSize  = (15,15),\r\n                  maxLevel = 0,\r\n                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))\r\n\r\n# Create some random colors\r\ncolor = np.random.randint(0,255,(100,3))\r\n\r\n# Take first frame and find corners in it\r\nret, old_frame = cap.read()\r\nold_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)\r\np0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)\r\n\r\n# Create a mask image for drawing purposes\r\nmask = np.zeros_like(old_frame)\r\n\r\nwhile(1):\r\n    ret,frame = cap.read()\r\n\r\n    if not ret:\r\n        break\r\n\r\n    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\r\n\r\n    # calculate optical flow\r\n    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)\r\n\r\n    # Select good points\r\n    good_new = p1[st==1]\r\n    good_old = p0[st==1]\r\n\r\n    # draw the tracks\r\n    for i,(new,old) in enumerate(zip(good_new,good_old)):\r\n        a,b = new.ravel()\r\n        c,d = old.ravel()\r\n        mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)\r\n        frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)\r\n    img = cv2.add(frame,mask)\r\n\r\n    cv2.imshow('frame',img)\r\n    k = cv2.waitKey(30) & 0xff\r\n    if k == 27:\r\n        break\r\n\r\n    # Now update the previous frame and previous points\r\n    old_gray = frame_gray.copy()\r\n    p0 = good_new.reshape(-1,1,2)\r\n\r\ncv2.destroyAllWindows()\r\n<\/pre>\n<p>\uc704\uc758 \uc608\uc81c\ub294 \ub2e4\uc74c \ucd94\uc801\ub41c \ud0a4\ud3ec\uc778\ud2b8\uac00 \uc5bc\ub9c8\ub098 \uc815\ud655\ud55c\uc9c0 \uac80\uc0ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uadf8\ub7ec\ubbc0\ub85c \uc5b4\ub5a4 \ud2b9\uc9d5\uc810 \ud3ec\uc778\ud2b8\uac00 \uc774\ubbf8\uc9c0\uc5d0\uc11c \uc0ac\ub77c\uc9c8 \uc218 \uc788\ub294\ub370, \uc774 \uacbd\uc6b0\ub77c\uace0 \ud560\uc9c0\ub77c\ub3c4 Optical Flow\ub294 \uc774\ub97c \uac1c\uc120\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc2e4\uc81c \ub354 \uacac\uace0\ud55c \ucd94\uc801\uc744 \uc704\ud574, \ud2b9\uc9d5\uc810\uc778 \ucf54\ub108\ub294 \ud2b9\uc815\ud55c \uad6c\uac04(\uc608\ub97c\ub4e4\uc5b4 5\uac1c\uc758 \ud504\ub808\uc784 \ub9c8\ub2e4)\uc5d0\uc11c \uac80\ucd9c\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4. \uc544\ub798\ub294 \uc2e4\ud589 \uacb0\uacfc\uc785\ub2c8\ub2e4.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.gisdeveloper.co.kr\/wp-content\/uploads\/2019\/05\/optical_flow_1.png\" alt=\"\" width=\"771\" height=\"609\" class=\"aligncenter size-full wp-image-6858\" \/><\/p>\n<p>\uc2e4\uc81c \uc2e4\ud589 \uacb0\uacfc\ub97c \ubcf4\uba74, \ub3d9\uc601\uc0c1 \uc18d\uc5d0\uc11c \uc774\ub3d9\ub418\ub294 \uac1d\uccb4(\uc0ac\ub78c)\uac00 \uc774\ub3d9\ub41c \uacbd\ub85c\ub85c \uc120\uc774 \uadf8\ub824\uc9c0\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\ub2e4\uc74c\uc740 \uc55e\uc11c \uc0b4\ud3b4\ubcf8, Optical Flow\ub97c \uc774\ub3d9 \uacbd\ub85c\ub85c \ubcf4\uc5ec\uc8fc\ub294 \uac83\uc774 \uc544\ub2cc \ubc00\ub3c4\ub85c \ubcf4\uc5ec\uc8fc\ub294 \uac83\uc744 \uc0b4\ud3b4\ubd05\ub2c8\ub2e4. \uc774\ub294 Gunner Farneback \uc54c\uace0\ub9ac\uc998\uc5d0 \uae30\ubc18\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uc544\ub798\uc758 \uc608\uc81c \ucf54\ub4dc\ub294 \uc774 \uc54c\uace0\ub9ac\uc998\uc744 \uc0ac\uc6a9\ud558\uc5ec Optical Flow\uc758 \ubc00\ub3c4(Dense)\ub97c \ubcf4\uc5ec\uc90d\ub2c8\ub2e4. <\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">\r\nimport cv2\r\nimport numpy as np\r\ncap = cv2.VideoCapture('.\/data\/vtest.avi')\r\n\r\nret, frame1 = cap.read()\r\nprvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)\r\nhsv = np.zeros_like(frame1)\r\nhsv[...,1] = 255\r\n\r\nwhile(1):\r\n    ret, frame2 = cap.read()\r\n    next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)\r\n\r\n    flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)\r\n\r\n    mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])\r\n    hsv[...,0] = ang*180\/np.pi\/2\r\n    hsv[...,2] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX)\r\n    rgb = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)\r\n\r\n    cv2.imshow('frame2',rgb)\r\n    k = cv2.waitKey(30) & 0xff\r\n    if k == 27:\r\n        break\r\n    elif k == ord('s'):\r\n        cv2.imwrite('opticalfb.png',frame2)\r\n        cv2.imwrite('opticalhsv.png',rgb)\r\n    prvs = next\r\n\r\ncap.release()\r\ncv2.destroyAllWindows()\r\n<\/pre>\n<p>\uc2e4\ud589 \uacb0\uacfc \uc911 \uc774\ubbf8\uc9c0\uc758 \ud55c \ucef7\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4. (\uc704 \uc608\uc81c\uc758 \ucf54\ub4dc\uc5d0 \ub530\ub77c s\ud0a4\ub97c \ub20c\ub7ec \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uc784)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.gisdeveloper.co.kr\/wp-content\/uploads\/2019\/05\/optical_flow_2.png\" alt=\"\" width=\"1536\" height=\"576\" class=\"aligncenter size-full wp-image-6860\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc774 \uae00\uc758 \uc6d0\ubb38\uc740 https:\/\/opencv-python-tutroals.readthedocs.io\/en\/latest\/py_tutorials\/py_video\/py_lucas_kanade\/py_lucas_kanade.html \uc785\ub2c8\ub2e4. \uc774 \uae00\uc5d0\uc11c\ub294 \uad11\ud559 \ud750\ub984(Optical Flow)\uc744 \uc774\ud574\ud558\uace0 Lucas-Kanade \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc774\ub97c \uc608\uce21\ud574 \ubcf4\ub294 \uc608\uc81c\ub97c \uc0b4\ud3b4\ubd05\ub2c8\ub2e4. OpenCv\uc5d0\uc11c\ub294 Lucas-Kanade \ubc29\ubc95\uc740 cv2.calcOpticalFlowPyrLK \ud568\uc218\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4. \uba3c\uc800 Optical Flow\ub294 \uce74\uba54\ub77c \ub610\ub294 \ubb3c\uccb4\uc758 \uc774\ub3d9\uc5d0 \uc758\ud574 \uc0dd\uae30\ub294 \uc5f0\uc18d\ub41c 2\uac1c\uc758 \uc774\ubbf8\uc9c0 \uac04\uc758 \uc5b4\ub5a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ud328\ud134\uc785\ub2c8\ub2e4. \uc774 \uc774\ub3d9 \ud328\ud134\uc740 \uccab\ubc88\uc7ac \ud504\ub808\uc784\uc5d0\uc11c \ub450\ubc88\uc9f8 \ud504\ub808\uc784 \uac04\uc758 \uc5b4\ub5a4 \uc9c0\uc810\uc758 \uc774\ub3d9\uc744 \ubcf4\uc5ec\uc8fc\ub294 2\ucc28\uc6d0 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/www.gisdeveloper.co.kr\/?p=6855\" class=\"more-link\">\ub354 \ubcf4\uae30<span class=\"screen-reader-text\"> &#8220;Python\uacfc OpenCV \u2013 41 : Optical Flow&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[130,131],"tags":[],"class_list":["post-6855","post","type-post","status-publish","format-standard","hentry","category-opencv","category-python"],"_links":{"self":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/6855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6855"}],"version-history":[{"count":6,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/6855\/revisions"}],"predecessor-version":[{"id":9424,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/6855\/revisions\/9424"}],"wp:attachment":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6855"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}