boofcv.alg.tracker.klt.PyramidKltTracker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of feature Show documentation
Show all versions of feature Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* Copyright (c) 2011-2014, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package boofcv.alg.tracker.klt;
import boofcv.struct.image.ImageSingleBand;
import boofcv.struct.pyramid.ImagePyramid;
/**
*
* A pyramid Kanade-Lucas-Tomasi (KLT) tracker that allows features to be tracker over a larger region than the basic
* ({@link KltTracker}) implementation. A feature is tracked at multiple resolutions, large motions can
* be detected at low resolution and are refined at higher resolutions.
*
*
*
* Tracking is allowed along the image border. A track is dropped if the smallest track is outside the image.
*
*
* @author Peter Abeles
*/
public class PyramidKltTracker {
// basic KLT tracker which works on a single image
protected KltTracker tracker;
// image pyramid for raw input image
protected ImagePyramid image;
// image pyramid for image gradient
protected DerivativeImage[] derivX;
protected DerivativeImage[] derivY;
public PyramidKltTracker(KltTracker tracker) {
this.tracker = tracker;
}
/**
* Sets the feature's description up. The feature's (x,y) must have already been set
* and {@link #setImage} been called.
*
* @param feature Feature's whose description is being setup.
* @return true if there was sufficient information to create a feature or false if not
*/
public boolean setDescription(PyramidKltFeature feature) {
for (int layer = 0; layer < image.getNumLayers(); layer++) {
float scale = (float)image.getScale(layer);
float x = feature.x / scale;
float y = feature.y / scale;
setupKltTracker(layer);
feature.desc[layer].setPosition(x, y);
if( !tracker.setDescription(feature.desc[layer]) )
return false;
}
return true;
}
/**
* Sets the current input images for the tracker to use.
* @param image Original image pyramid.
* @param derivX Derivative along x-axis.
* @param derivY Derivative along y-axis.
*/
public void setImage(ImagePyramid image,
DerivativeImage[] derivX, DerivativeImage[] derivY) {
if( image.getNumLayers() != derivX.length || image.getNumLayers() != derivY.length )
throw new IllegalArgumentException("Number of layers does not match.");
this.image = image;
this.derivX = derivX;
this.derivY = derivY;
}
/**
* Only sets the image pyramid. The derivatives are set to null. Only use this when tracking.
* @param image Image pyramid
*/
public void setImage(ImagePyramid image ) {
this.image = image;
this.derivX = null;
this.derivY = null;
}
/**
*
* Finds the feature's new location in the image. The feature's position can be modified even if
* tracking fails.
*
*
*
* NOTE: The feature's description is not updated and tracking over several frames can break down
* if its description is not updated.
*
*
* @param feature The feature being tracked.
* @return If tracking failed or not.
*/
public KltTrackFault track(PyramidKltFeature feature) {
// this is the first level it was able to track the feature at
int firstLevelTracked = -1;
float x = feature.x;
float y = feature.y;
// track from the top of the pyramid to the bottom
for (int layer = image.getNumLayers()-1; layer >= 0; layer--) {
float scale = (float)image.getScale(layer);
x /= scale;
y /= scale;
// tracking never needs the derivative
tracker.unsafe_setImage(image.getLayer(layer), null, null);
KltFeature f = feature.desc[layer];
f.setPosition(x, y);
KltTrackFault ret = tracker.track(f);
if (ret == KltTrackFault.SUCCESS) {
if( firstLevelTracked == -1 )
firstLevelTracked = layer;
// nothing bad happened, save this result
x = feature.desc[layer].x;
y = feature.desc[layer].y;
} else {
// tracking failed
return ret;
}
x *= scale;
y *= scale;
}
feature.setPosition(x, y);
return KltTrackFault.SUCCESS;
}
/**
* Average error between track template and the image.
*
* @see boofcv.alg.tracker.klt.KltTracker#getError()
*
* @return error
*/
public float getError() {
return tracker.getError();
}
private void setupKltTracker(int layer) {
if (derivX != null)
tracker.unsafe_setImage(image.getLayer(layer), derivX[layer], derivY[layer]);
else
tracker.unsafe_setImage(image.getLayer(layer), null, null);
}
}