@Override
  public List<Point2D_F64> getInitial() {
    List<Point2D_F64> initial = new ArrayList<Point2D_F64>();

    for (PyramidKltFeature t : tracks) {
      initial.add((Point2D_F64) t.getCookie());
    }

    return initial;
  }
  @Override
  public void track(I image) {

    // update the image pyramid
    pyramid.process(image);
    if (derivX == null) {
      derivX = PyramidOps.declareOutput(pyramid, derivType);
      derivY = PyramidOps.declareOutput(pyramid, derivType);
    }
    PyramidOps.gradient(pyramid, gradient, derivX, derivY);

    tracker.setInputs(pyramid, derivX, derivY);

    if (first) {
      first = false;

      detector.detect(image);

      for (int i = 0; i < detector.getNumberOfFeatures(); i++) {
        Point2D_F64 p = detector.getLocation(i);

        PyramidKltFeature t = tracker.createNewTrack();

        t.cookie = p.copy();
        tracker.setDescription((float) p.x, (float) p.y, t);

        tracks.add(t);
      }
    } else {
      for (int i = 0; i < tracks.size(); ) {
        PyramidKltFeature t = tracks.get(i);

        if (!tracker.performTracking(t)) {
          tracks.remove(i);
        } else {
          i++;
        }
      }
    }
  }