Difference between revisions of "Example Tracker Mean Shift"

From BoofCV
Jump to navigationJump to search
(Created page with "<center> <gallery widths=400px heights=300px> file:Example_tracking_meanshift.jpg | Mean-shift was used to track the ball across this video sequence. </gallery> </center> In ...")
 
m
(8 intermediate revisions by the same user not shown)
Line 5: Line 5:
</center>
</center>


In this example mean-shift is used to track a color ball.  Mean-shift performs a local search that attempts to maximize the similarity of the color in its kernel to the color in its model.  It is a fairly robust and fast tracker.  If you are lucky, it will sometimes even reaquire a track after it has been lost.
BoofCV provides two mean-shift trackers, histogram and pixel likelihood, this example is for the second.  It is demonstrated how to create a custom pixel likelihood fuction to track a color ball.  Mean-shift performs a local search that attempts to maximize the similarity of the color in its kernel to the color in its model.  It is a fairly robust and fast tracker.  If you are lucky, it will sometimes even reaquire a track after it has been lost.


Example Code:
Example Code:
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.16/examples/src/boofcv/examples/tracking/ExampleTrackerMeanShift.java ExampleTrackerMeanShift.java]
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.28/examples/src/main/java/boofcv/examples/tracking/ExampleTrackerMeanShiftLikelihood.java ExampleTrackerMeanShiftLikelihood.java]


Concepts:
Concepts:
Line 14: Line 14:
* Color histogram
* Color histogram
* Mean-shift
* Mean-shift
Relevant Applets:
* [[Applet Object Tracking| Object Tracking]]


= Example Code =
= Example Code =
Line 22: Line 19:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
/**
/**
  * Mean-shift based trackers use color information to perform a local search. The Comaniciu based trackers match
  * Example of how to use the low level implementation of mean-shift to track a specific color provided by the user.
  * the color histogram directly, are more robust to objects with complex distributions, and can be configured to
  * The weights of each pixel is computed by RgbLikelihood, see below, and track regions are rectangularThis
* estimate the object's scaleLikelihood based trackers use color to compute a likelihood
  * tracker works very well since the ball is almost uniformly blueIf the light varried then a HSV color
  * function, which mean-shift is then run onThe likelihood based trackers are very fast but only work well
  * model might be better.
  * when the target is composed of a single color.
  *
  *
  * @author Peter Abeles
  * @author Peter Abeles
  */
  */
public class ExampleTrackerMeanShift {
public class ExampleTrackerMeanShiftLikelihood {
 
/**
* Very simple implementation of PixelLikelihood.  Uses linear distance to compute how close
* a color is to the target color.
*/
public static class RgbLikelihood implements PixelLikelihood<Planar<GrayU8>> {
 
int targetRed,targetGreen,targetBlue;
float radius = 35;
Planar<GrayU8> image;
 
public RgbLikelihood(int targetRed, int targetGreen, int targetBlue) {
this.targetRed = targetRed;
this.targetGreen = targetGreen;
this.targetBlue = targetBlue;
}
 
@Override
public void setImage(Planar<GrayU8> image) {
this.image = image;
}
 
@Override
public boolean isInBounds(int x, int y) {
return image.isInBounds(x,y);
}
 
/**
* This function is used to learn the target's model from the select image region.  Since the
* model is provided in the constructor it isn't needed or used.
*/
@Override
public void createModel(RectangleLength2D_I32 target) {
throw new RuntimeException("Not supported");
}
 
@Override
public float compute(int x, int y) {
int pixelR = image.getBand(0).get(x,y);
int pixelG = image.getBand(1).get(x,y);
int pixelB = image.getBand(2).get(x,y);
 
// distance along each color band
float red = Math.max(0, 1.0f - Math.abs(targetRed - pixelR) / radius);
float green = Math.max(0,1.0f - Math.abs(targetGreen-pixelG)/radius);
float blue = Math.max(0,1.0f - Math.abs(targetBlue-pixelB)/radius);
 
// multiply them all together
return red*green*blue;
}
}
 
public static void main(String[] args) {
public static void main(String[] args) {
MediaManager media = DefaultMediaManager.INSTANCE;
MediaManager media = DefaultMediaManager.INSTANCE;
String fileName = "../data/applet/tracking/balls_blue_red.mjpeg";
String fileName = UtilIO.pathExample("tracking/balls_blue_red.mjpeg");
Quadrilateral_F64 location = new Quadrilateral_F64(394,247,474,244,475,325,389,321);
RectangleLength2D_I32 location = new RectangleLength2D_I32(394,247,475-394,325-247);


ImageType<MultiSpectral<ImageUInt8>> imageType = ImageType.ms(3,ImageUInt8.class);
ImageType<Planar<GrayU8>> imageType = ImageType.pl(3,GrayU8.class);


SimpleImageSequence<MultiSpectral<ImageUInt8>> video = media.openVideo(fileName, imageType);
SimpleImageSequence<Planar<GrayU8>> video = media.openVideo(fileName, imageType);


// Create the tracker.  Comment/Uncomment to change the tracker.
// Return a higher likelihood for pixels close to this RGB color
TrackerObjectQuad<MultiSpectral<ImageUInt8>> tracker =
RgbLikelihood likelihood = new RgbLikelihood(64,71,69);
FactoryTrackerObjectQuad.meanShiftComaniciu2003(new ConfigComaniciu2003(), imageType);
 
// FactoryTrackerObjectQuad.meanShiftComaniciu2003(new ConfigComaniciu2003(true),imageType);
TrackerMeanShiftLikelihood<Planar<GrayU8>> tracker =
// FactoryTrackerObjectQuad.meanShiftLikelihood(30,5,255, MeanShiftLikelihoodType.HISTOGRAM,imageType);
new TrackerMeanShiftLikelihood<>(likelihood, 50, 0.1f);


// specify the target's initial location and initialize with the first frame
// specify the target's initial location and initialize with the first frame
 
Planar<GrayU8> frame = video.next();
MultiSpectral<ImageUInt8> frame = video.next();
// Note that the tracker will not automatically invoke RgbLikelihood.createModel() in its initialize function
tracker.initialize(frame,location);
tracker.initialize(frame,location);


Line 54: Line 102:
TrackerObjectQuadPanel gui = new TrackerObjectQuadPanel(null);
TrackerObjectQuadPanel gui = new TrackerObjectQuadPanel(null);
gui.setPreferredSize(new Dimension(frame.getWidth(),frame.getHeight()));
gui.setPreferredSize(new Dimension(frame.getWidth(),frame.getHeight()));
gui.setBackGround((BufferedImage)video.getGuiImage());
gui.setImageUI((BufferedImage)video.getGuiImage());
gui.setTarget(location,true);
gui.setTarget(location,true);
ShowImages.showWindow(gui, "Tracking Results");
ShowImages.showWindow(gui, "Tracking Results", true);


// Track the object across each video frame and display the results
// Track the object across each video frame and display the results
Line 62: Line 110:
frame = video.next();
frame = video.next();


boolean visible = tracker.process(frame,location);
boolean visible = tracker.process(frame);


gui.setBackGround((BufferedImage) video.getGuiImage());
gui.setImageUI((BufferedImage) video.getGuiImage());
gui.setTarget(location,visible);
gui.setTarget(tracker.getLocation(),visible);
gui.repaint();
gui.repaint();



Revision as of 00:03, 20 January 2018

BoofCV provides two mean-shift trackers, histogram and pixel likelihood, this example is for the second. It is demonstrated how to create a custom pixel likelihood fuction to track a color ball. Mean-shift performs a local search that attempts to maximize the similarity of the color in its kernel to the color in its model. It is a fairly robust and fast tracker. If you are lucky, it will sometimes even reaquire a track after it has been lost.

Example Code:

Concepts:

  • Object tracking
  • Color histogram
  • Mean-shift

Example Code

/**
 * Example of how to use the low level implementation of mean-shift to track a specific color provided by the user.
 * The weights of each pixel is computed by RgbLikelihood, see below, and track regions are rectangular.  This
 * tracker works very well since the ball is almost uniformly blue.  If the light varried then a HSV color
 * model might be better.
 *
 * @author Peter Abeles
 */
public class ExampleTrackerMeanShiftLikelihood {

	/**
	 * Very simple implementation of PixelLikelihood.  Uses linear distance to compute how close
	 * a color is to the target color.
	 */
	public static class RgbLikelihood implements PixelLikelihood<Planar<GrayU8>> {

		int targetRed,targetGreen,targetBlue;
		float radius = 35;
		Planar<GrayU8> image;

		public RgbLikelihood(int targetRed, int targetGreen, int targetBlue) {
			this.targetRed = targetRed;
			this.targetGreen = targetGreen;
			this.targetBlue = targetBlue;
		}

		@Override
		public void setImage(Planar<GrayU8> image) {
			this.image = image;
		}

		@Override
		public boolean isInBounds(int x, int y) {
			return image.isInBounds(x,y);
		}

		/**
		 * This function is used to learn the target's model from the select image region.  Since the
		 * model is provided in the constructor it isn't needed or used.
		 */
		@Override
		public void createModel(RectangleLength2D_I32 target) {
			throw new RuntimeException("Not supported");
		}

		@Override
		public float compute(int x, int y) {
			int pixelR = image.getBand(0).get(x,y);
			int pixelG = image.getBand(1).get(x,y);
			int pixelB = image.getBand(2).get(x,y);

			// distance along each color band
			float red = Math.max(0, 1.0f - Math.abs(targetRed - pixelR) / radius);
			float green = Math.max(0,1.0f - Math.abs(targetGreen-pixelG)/radius);
			float blue = Math.max(0,1.0f - Math.abs(targetBlue-pixelB)/radius);

			// multiply them all together
			return red*green*blue;
		}
	}

	public static void main(String[] args) {
		MediaManager media = DefaultMediaManager.INSTANCE;
		String fileName = UtilIO.pathExample("tracking/balls_blue_red.mjpeg");
		RectangleLength2D_I32 location = new RectangleLength2D_I32(394,247,475-394,325-247);

		ImageType<Planar<GrayU8>> imageType = ImageType.pl(3,GrayU8.class);

		SimpleImageSequence<Planar<GrayU8>> video = media.openVideo(fileName, imageType);

		// Return a higher likelihood for pixels close to this RGB color
		RgbLikelihood likelihood = new RgbLikelihood(64,71,69);

		TrackerMeanShiftLikelihood<Planar<GrayU8>> tracker =
				new TrackerMeanShiftLikelihood<>(likelihood, 50, 0.1f);

		// specify the target's initial location and initialize with the first frame
		Planar<GrayU8> frame = video.next();
		// Note that the tracker will not automatically invoke RgbLikelihood.createModel() in its initialize function
		tracker.initialize(frame,location);

		// For displaying the results
		TrackerObjectQuadPanel gui = new TrackerObjectQuadPanel(null);
		gui.setPreferredSize(new Dimension(frame.getWidth(),frame.getHeight()));
		gui.setImageUI((BufferedImage)video.getGuiImage());
		gui.setTarget(location,true);
		ShowImages.showWindow(gui, "Tracking Results", true);

		// Track the object across each video frame and display the results
		while( video.hasNext() ) {
			frame = video.next();

			boolean visible = tracker.process(frame);

			gui.setImageUI((BufferedImage) video.getGuiImage());
			gui.setTarget(tracker.getLocation(),visible);
			gui.repaint();

			BoofMiscOps.pause(20);
		}
	}
}