/*
* Copyright (c) 2011-2016, 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.demonstrations.tracker;
import boofcv.abst.tracker.*;
import boofcv.core.image.GConvertImage;
import boofcv.core.image.GeneralizedImageOps;
import boofcv.factory.tracker.FactoryTrackerObjectQuad;
import boofcv.gui.VideoProcessAppBase;
import boofcv.gui.image.ShowImages;
import boofcv.gui.tracker.TrackerObjectQuadPanel;
import boofcv.io.PathLabel;
import boofcv.io.UtilIO;
import boofcv.io.image.SimpleImageSequence;
import boofcv.struct.image.GrayU8;
import boofcv.struct.image.ImageGray;
import boofcv.struct.image.ImageType;
import boofcv.struct.image.Planar;
import georegression.struct.shapes.Quadrilateral_F64;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
/**
* Let's the user select a region in the image and tracks it using different algorithms.
*
* @author Peter Abeles
*/
public class VideoTrackerObjectQuadApp
extends VideoProcessAppBase>
implements TrackerObjectQuadPanel.Listener , TrackerQuadInfoPanel.Listener
{
Class imageClass;
TrackerObjectQuad tracker;
TrackerObjectQuadPanel videoPanel;
TrackerQuadInfoPanel infoBar;
int whichAlg;
I gray;
Quadrilateral_F64 target = new Quadrilateral_F64();
Quadrilateral_F64 targetDefault = new Quadrilateral_F64();
boolean targetSelected = false;
boolean selectionChanged = false;
boolean success;
boolean processedInputImage = false;
boolean firstFrame = true;
public VideoTrackerObjectQuadApp( Class imageType ) {
super(1, ImageType.pl(3, imageType));
this.imageClass = imageType;
gray = GeneralizedImageOps.createSingleBand(imageType,1,1);
addAlgorithm(0, "Circulant", 0);
addAlgorithm(0, "TLD", 1);
addAlgorithm(0, "Mean-Shift Region Fixed", 2);
addAlgorithm(0, "Mean-Shift Region Scale", 3);
addAlgorithm(0, "Mean-Shift Pixel", 4);
addAlgorithm(0, "Sparse Flow Tracker", 5);
videoPanel = new TrackerObjectQuadPanel(this);
infoBar = new TrackerQuadInfoPanel(this);
add(infoBar, BorderLayout.WEST);
add(videoPanel, BorderLayout.CENTER);
setMainGUI(videoPanel);
}
@Override
public void process( final SimpleImageSequence> sequence ) {
// stop the image processing code
stopWorker();
this.sequence = sequence;
sequence.setLoop(false);
setPause(false);
if( !sequence.hasNext() )
throw new IllegalArgumentException("Empty sequence");
// start everything up and resume processing
doRefreshAll();
}
@Override
public void refreshAll(Object[] cookies) {
if( whichAlg == 0 )
tracker = FactoryTrackerObjectQuad.circulant(new ConfigCirculantTracker(), imageClass);
else if( whichAlg == 1 )
tracker = FactoryTrackerObjectQuad.tld(new ConfigTld(false),imageClass);
else if( whichAlg == 2 ) {
ConfigComaniciu2003 config = new ConfigComaniciu2003();
config.scaleChange = 0;
tracker = FactoryTrackerObjectQuad.meanShiftComaniciu2003(config,imageType);
} else if( whichAlg == 3 ) {
ConfigComaniciu2003 config = new ConfigComaniciu2003();
config.scaleChange = 0.05f;
tracker = FactoryTrackerObjectQuad.meanShiftComaniciu2003(config,imageType);
} else if( whichAlg == 4 ) {
tracker = FactoryTrackerObjectQuad.meanShiftLikelihood(30, 5, 256, MeanShiftLikelihoodType.HISTOGRAM, imageType);
} else if( whichAlg == 5 ) {
tracker = FactoryTrackerObjectQuad.sparseFlow(null,imageClass,null);
} else
throw new RuntimeException("Unknown algorithm");
// use default rectangle
videoPanel.setDefaultTarget(targetDefault);
firstFrame = true;
targetSelected = true;
selectionChanged = true;
target.set(targetDefault);
setPause(false);
startWorkerThread();
}
@Override
public void setActiveAlgorithm(int indexFamily, String name, Object cookie) {
stopWorker();
whichAlg = (Integer)cookie;
sequence.reset();
refreshAll(null);
}
@Override
protected void updateAlg(Planar frame, BufferedImage buffImage) {
boolean grayScale = false;
if( tracker.getImageType().getFamily() == ImageType.Family.GRAY) {
gray.reshape(frame.width,frame.height);
GConvertImage.average(frame, gray);
grayScale = true;
}
if( targetSelected ) {
if( selectionChanged ) {
selectionChanged = false;
if( grayScale)
success = tracker.initialize(gray, target);
else
success = tracker.initialize(frame, target);
} else
if( grayScale)
success = tracker.process(gray, target);
else
success = tracker.process(frame, target);
}
processedInputImage = true;
}
@Override
protected void updateAlgGUI(Planar frame, BufferedImage imageGUI, double fps) {
if( firstFrame ) {
videoPanel.setPreferredSize(new Dimension(imageGUI.getWidth(),imageGUI.getHeight()));
videoPanel.setBackGround((BufferedImage) sequence.getGuiImage());
infoBar.setFPS(0);
infoBar.setTracking("");
firstFrame = false;
setPause(true);
} else {
videoPanel.setBackGround((BufferedImage) sequence.getGuiImage());
videoPanel.setTarget(target, success);
infoBar.setFPS(fps);
if( success ) {
infoBar.setTracking("FOUND");
} else {
infoBar.setTracking("?");
}
videoPanel.repaint();
}
}
@Override
public void selectedTarget(Quadrilateral_F64 target) {
System.out.println(target.a.x+" "+target.a.y+" "+target.b.x+" "+target.b.y+" "+target.c.x+" "+target.c.y+" "+target.d.x+" "+target.d.y);
this.target.set(target);
targetSelected = true;
selectionChanged = true;
setPause(false);
}
@Override
public void togglePause() {
setPause(!isPaused);
}
@Override
public void selectTarget() {
setPause(true);
infoBar.setTracking("");
targetSelected = false;
videoPanel.enterSelectMode();
}
@Override
public void resetVideo() {
stopWorker();
sequence.reset();
refreshAll(null);
}
@Override
public void changeInput(String name, int index) {
processedInputImage = false;
String videoName = inputRefs.get(index).getPath();
String path = videoName.substring(0,videoName.lastIndexOf('.'));
parseQuad(path+"_rect.txt");
SimpleImageSequence> video = media.openVideo(videoName, ImageType.pl(3, imageClass));
process(video);
}
private void parseQuad( String fileName ) {
Reader r = media.openFile(fileName);
BufferedReader in = new BufferedReader(r);
try {
String w[] = in.readLine().split(" ");
if( w.length != 8 )
throw new RuntimeException("Unexpected number of variables in rectangle: "+w.length);
targetDefault.a.x = Double.parseDouble(w[0]);
targetDefault.a.y = Double.parseDouble(w[1]);
targetDefault.b.x = Double.parseDouble(w[2]);
targetDefault.b.y = Double.parseDouble(w[3]);
targetDefault.c.x = Double.parseDouble(w[4]);
targetDefault.c.y = Double.parseDouble(w[5]);
targetDefault.d.x = Double.parseDouble(w[6]);
targetDefault.d.y = Double.parseDouble(w[7]);
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 0 = running
* 1 = paused
* 2 = finished
*/
@Override
protected void handleRunningStatus(int status) {
if( status == 0 ) {
infoBar.setPlay(false);
} else if( status == 1 ) {
infoBar.setPlay(true);
}
}
@Override
public void loadConfigurationFile(String fileName) {}
@Override
public boolean getHasProcessedImage() {
return processedInputImage;
}
public static void main(String[] args) {
// Class type = GrayF32.class;
Class type = GrayU8.class;
VideoTrackerObjectQuadApp app = new VideoTrackerObjectQuadApp(type);
// app.setBaseDirectory(UtilIO.pathExample("");
// app.loadInputData(UtilIO.pathExample("tracking/file_list.txt");
java.util.List inputs = new ArrayList();
inputs.add(new PathLabel("WildCat", UtilIO.pathExample("tracking/wildcat_robot.mjpeg")));
inputs.add(new PathLabel("Tree", UtilIO.pathExample("tracking/tree.mjpeg")));
inputs.add(new PathLabel("Book", UtilIO.pathExample("tracking/track_book.mjpeg")));
inputs.add(new PathLabel("Face", UtilIO.pathExample("tracking/track_peter.mjpeg")));
inputs.add(new PathLabel("Chipmunk", UtilIO.pathExample("tracking/chipmunk.mjpeg")));
inputs.add(new PathLabel("Balls", UtilIO.pathExample("tracking/balls_blue_red.mjpeg")));
inputs.add(new PathLabel("Driving Snow", UtilIO.pathExample("tracking/snow_follow_car.mjpeg")));
inputs.add(new PathLabel("Driving Night", UtilIO.pathExample("tracking/night_follow_car.mjpeg")));
app.setInputList(inputs);
// wait for it to process one image so that the size isn't all screwed up
while( !app.getHasProcessedImage() ) {
Thread.yield();
}
ShowImages.showWindow(app, "Tracking Rectangle",true);
}
}
Ads help maintain this website.