Lucas Kanade Optical Flow Implementation

asked 2015-05-29 07:09:45 -0600

Gustav gravatar image

I was working on my own optical flow script using lucas kanade method on python and numpy. But I get really different flow results with the opencv implementation of that algorithm (This is testing video), than with my own.
This is the full code:

import cv2
import numpy as np

def drawlines (image, pts0, pts1, color):
    for pt0, pt1 in zip(pts0, pts1):
        cv2.line(image,(pt0[0],pt0[1]),(pt1[0],pt1[1]),color,thickness=2);

def calcFlowLib (prev, curr, points):
    #USING OPENCV IMPLEMENTATION
    currpts = np.reshape(points,(-1,1,2));
    lk_params = dict(winSize=(41,41), maxLevel=0, criteria=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,0.03));
    nextpts, stat, err = cv2.calcOpticalFlowPyrLK(prev,curr,currpts,None,**lk_params);
    nextpts = np.reshape(nextpts,(-1,2));
    return nextpts;

def calcFlow (im1, im2, points, halfwin=(20,20)):
    #MY IMPLEMENTATION
    pts = np.copy(points)
    npts = points.shape[0]

    i_x = np.zeros(im1.shape)
    i_y = np.zeros(im1.shape)
    i_t = np.zeros(im1.shape)
    i_x[1:-1, 1:-1] = (im1[1:-1, 2:] - im1[1:-1, :-2]) / 2
    i_y[1:-1, 1:-1] = (im1[2:, 1:-1] - im1[:-2, 1:-1]) / 2
    i_t = im1 - im2


    for i in xrange(0,npts,1):
        p = pts[i]

        ix = i_x[p[1]-halfwin[1]:p[1]+halfwin[1]+1,p[0]-halfwin[0]:p[0]+halfwin[0]+1]
        iy = i_y[p[1]-halfwin[1]:p[1]+halfwin[1]+1,p[0]-halfwin[0]:p[0]+halfwin[0]+1]            
        it = i_t[p[1]-halfwin[1]:p[1]+halfwin[1]+1,p[0]-halfwin[0]:p[0]+halfwin[0]+1]

        A = np.matrix([np.ravel(ix),np.ravel(iy)],dtype=np.float32)
        B = np.matrix([np.ravel(it)],dtype=np.float32)
        v = np.linalg.lstsq(A*A.T, A*B.T)[0]
        pts[i] = p + np.ravel(v)
    return pts


cap = cv2.VideoCapture("OF.mp4")    
prevgray = None
currgray = None
prevpts0 = np.array([[320,180],[100,100]],dtype=np.float32)
prevpts1 = np.array([[320,180],[100,100]],dtype=np.float32)
while(cap.isOpened()):
    ret, frame = cap.read()
    if not ret:
        break
    frame = cv2.resize(frame,(640,360))
    currgray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

    if(prevgray is not None):
        currpts0 = calcFlow(prevgray,currgray,prevpts0)
        drawlines(frame,prevpts0,currpts0,(0,255,0)) 
        currpts1 = calcFlowLib(prevgray,currgray,prevpts1)
        drawlines(frame,prevpts1,currpts1,(0,0,255))
        prevpts0 = np.copy(currpts0) 
        prevpts1 = np.copy(currpts1)

    prevgray = np.copy(currgray)
    cv2.imshow("Frame",frame)
    if cv2.waitKey(1) & 0xFF == ord('1'):
        break
cap.release()
cv2.destroyAllWindows()

Where is the wrong part of my implementation?

edit retag flag offensive close merge delete

Comments

I didn't investigate into your source code but one of the possible difference is that OpenCV use a pyramidal implementation for the Lucas-Kanade optical flow method.

Eduardo gravatar imageEduardo ( 2015-05-29 17:20:42 -0600 )edit

I set maxLevel=0 for opencv lucas kanade implementation. If I don't wrong, the calculation should be same with non pyramidal implementation..

Gustav gravatar imageGustav ( 2015-05-30 00:32:59 -0600 )edit