The Lucas-Kanade (LK) algorithm was originally proposed in 1981, and it has become one of the most successful methods available in Computer Vision. Currently, this method is typically applied to a subset of key points in the input image. This method assumes that optical flow is a necessary constant in a local neighborhood of the pixel that is under consideration and solves the basic Optical Flow technique equations you can see equation (1), for each pixel (x, y) on that neighborhood. The method also assumes that displacements between two consecutive frames are small and are approximately a way to get an over-constrained system of the considered points:
I(x, y, t) = I(x + ∆x, y + ∆y, t + ∆t) (1)
We will now focus on the
Pyramidal Lucas-Kanade method, which estimates the optical flow in a pyramid using the calcOpticalFlowPyrLK()
function. This method first estimates the optical flow at the top of the pyramid, thus avoiding the problems caused by violations of our assumptions of small and coherent motion. The motion estimate from this first level is then used as the starting point to estimate motion at the next level, as shown in the pyramid in the following diagram:
The following example uses the maxMovementLK
function to implement a motion detector:
void maxMovementLK(Mat& prev_frame, Mat& frame) { // 1-Detect right features to apply the Optical Flow technique vector<Point2f> initial_features; goodFeaturesToTrack(prev_frame, initial_features,MAX_FEATURES, 0.1, 0.2 ); // 2-Set the parameters vector<Point2f>new_features; vector<uchar>status; vector<float> err; TermCriteria criteria(TermCriteria::COUNT | TermCriteria::EPS, 20, 0.03); Size window(10,10); int max_level = 3; int flags = 0; double min_eigT = 0.004; // 3-Lucas-Kanade method for the Optical Flow technique calcOpticalFlowPyrLK(prev_frame, frame, initial_features, new_features, status, err, window, max_level, criteria, flags, min_eigT ); // 4-Show the results double max_move = 0; double movement = 0; for(int i=0; i<initial_features.size(); i++) { Point pointA (initial_features[i].x, initial_features[i].y); Point pointB(new_features[i].x, new_features[i].y); line(prev_frame, pointA, pointB, Scalar(255,0,0), 2); movement = norm(pointA-pointB); if(movement > max_move) max_move = movement; } if(max_move >MAX_MOVEMENT) { putText(prev_frame,"INTRUDER",Point(100,100),FONT_ITALIC,3,Scalar(255,0,0),5); imshow("Video Camera", prev_frame); cout << "Press a key to continue..." << endl; waitKey(); } }
The preceding example shows you a window with each movement. If there is a large movement, a message is displayed on the screen. Firstly, we need to obtain a set of appropriate key points in the image on which we can estimate the optical flow. The goodFeaturesToTrack()
function uses the method that was originally proposed by Shi and Tomasi to solve this problem in a reliable way, although you can also use other functions to detect important and easy-to-track features (see Chapter 5, Focusing on the Interesting 2D Features). MAX_FEATURES
is set to 500
to limit the number of key points. The Lucas-Kanade method parameters are then set and calcOpticalFlowPyrLK()
is called. When the function returns, the status (status
) array is checked to see which points were successfully tracked and that the new set of points (new_features
) with the estimated positions is used. Lines are drawn to represent the motion, and if there is a displacement greater than MAX_MOVEMENT
—for example—100, a message is shown on the screen. We can see two screen captures, as follows:
Using the modified videoCamera
example, we have applied the maxMovementLK()
function to detect large movements:
... while(!finish) { capture.read(frame); cvtColor(frame,frame,COLOR_BGR2GRAY); // Detect Maximum Movement with Lucas-Kanade Method maxMovementLK(prev_frame, frame); ...
This method is computationally efficient because tracking is only performed on important or interesting points.