2
votes

I'm trying to run python example from OpenCV site:

http://docs.opencv.org/trunk/d7/d8b/tutorial_py_lucas_kanade.html

import numpy as np
import cv2
cap = cv2.VideoCapture('slow.flv')
# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
                       qualityLevel = 0.3,
                       minDistance = 7,
                       blockSize = 7 )
# Parameters for lucas kanade optical flow
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# Create some random colors
color = np.random.randint(0,255,(100,3))
# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)
while(1):
    ret,frame = cap.read()
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # calculate optical flow
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    # Select good points
    good_new = p1[st==1]
    good_old = p0[st==1]
    # draw the tracks
    for i,(new,old) in enumerate(zip(good_new,good_old)):
        a,b = new.ravel()
        c,d = old.ravel()
        mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
        frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
    img = cv2.add(frame,mask)
    cv2.imshow('frame',img)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
    # Now update the previous frame and previous points
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)
cv2.destroyAllWindows()
cap.release()

I use Python 3 to run this example

It works but only for 5-15 seconds for my videos and then stops with next error:

Traceback (most recent call last): File "o.py", line 28, in good_new = p1[st==1] TypeError: 'NoneType' object is not subscriptable

What can be wrong in this example?

1
calcOpticalFlowPyrLK may have not returned found any nextPts hence p1 is empty. Why don't you check for emptiness first before selecting good points? Add if p1 not None: ...... I'd also recommend printing out its value to see for yourself if that's the case. Let me know if it works ;) - eshirima
yeah I did this and in printed empty array - [], I tried try catch and continue when this happens but then video becomes just paused - user924
You could also just encapsulate the remainder of your code inside the if statement because it doesn't make sense to continue if good_new is empty - eshirima
@eshirima of course it was I meant, I put except after p0 = good_new.reshape(-1,1,2) - user924
Can u update your code - eshirima

1 Answers

4
votes

That happens if the all the optical flow objects (the color dots on your screen) go out of the frame. Do this- if the array p1 is empty, find features again and then calculate optical flow. That should work.

Add this in the while loop( But it simply fills your entire screen with lines over time) :

if p1 is None:
   p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
   p1, st, err = cv2.calcOpticalFlowPyrLK(...., **lk_params)