Stackimus Prime
Stackimus Prime

Reputation: 169

Getting previous frame from video Opencv Haar Cascade

I'm using a cars cascade to detect all cars in a sample video. The program is currently drawing rectangles around each car it has detected. However, the rectangles keep on changing size from frame to frame. I would like to add some stabilization by keeping the original rectangle if the new rectangle from the next frame overlaps with the previous rectangle. To implement this, I am saving the previous frame (and detecting the cars from the previous frame) and comparing the rectangles of the previous frame with the current frame.

 Mat frame;
Mat prevFrame;

while (capture.isOpened()) {
    capture.read(frame);
    vector<Rect> cars; // center of rectangles where each rectangle contains the detected object
    vector<Rect> prevCars; // to store previous tracked rectangles

    // Detects objects of different sizes in the input image. The detected objects are returned as a list of rectangles.
    car_cascade.detectMultiScale(frame, cars, 1.1, 2);

    if(!prevFrame.empty()) {
        car_cascade.detectMultiScale(prevFrame, prevCars, 1.1, 2);
    } else {
        cout << "EMPTY" << endl; // for testing
    }

    cout << "current : " << cars.size() << endl; // print out number of cars
    cout << "previous: " << prevCars.size() << endl; // print out number of cars


    // more code goes here which I haven't written here

    frame.copyTo(prevFrame); // set previous frame to current frame
    imshow("Video", frame);

    char key = waitKey(33);
    if (key == 'q')
    {
        break;
    }
}

However, the number of cars detected from the previous frame is not the same as the previous current. E.g.,

EMPTY current : 3 previous: 0 <- 0 because it is empty current : 3 previous: 2 <- previous is 2, but should be 3 since the previous current was 3 current : 3 previous: 2

Upvotes: 2

Views: 451

Answers (1)

Elouarn Laine
Elouarn Laine

Reputation: 1695

In order to track and update cars' Rect, here is what I would do (python like code):

def getIndexOfCorrespondingTrackedCar(car) :
    for i in range(0, len(tracked_cars)) :
        if distance(car.center, tracked_cars[i].center) < THRESHOLD : // you will have to define a threshold according to your case. It has to be smaller than the speed of cars (in px/frame) though.
            return(i) // we found the corresponding car in the tracked_cars list
    return(-1) // we found no corresponding car, it must be a new car

tracked_cars = [] // list of tracked Rects
cars_current_frame = [] // list of Rects on the current frame

while(camera.open()) :

    cars_current_frame = getCarsInFrame(frame) // here you want to use your detectMultiScale function

    for ccf in cars_current_frame :
        car_idx = getIndexOfCorrespondingTrackedCar(ccf) // get the index of the corresponding car in tracked_cars list
        if car_idx is -1 : // No correspondance has been found, this is a new car
            tracked_cars.append(ccf)
        else :
            tracked_cars[car_idx] = ccf // we update the position of the tracked car with its new position

    deleteOutdatedCars(tracked_cars) // delete all the tracked cars that haven't been updated for a certain time (it most probably means that the car went off of the frame)

In my example, I only use lists of Rects, but it would be more convenient to use objects here. I recommend you to create a Car class with the following member variables :

  • a Rect to keep track of the car's position
  • a time stamp of the last update (this will be needed to delete the "outdated" cars)
  • a speed vector to approximate the position of the car on the next frame (optional)

I used a similar approach with a hand tracking system and it worked well.

Upvotes: 1

Related Questions