1 /**
2 * Copyright (c) 2011, The University of Southampton and the individual contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the University of Southampton nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 /**
31 *
32 */
33 package org.openimaj.video.processing.motion;
34
35 import java.util.LinkedList;
36 import java.util.Map;
37 import java.util.Queue;
38
39 import org.openimaj.image.FImage;
40 import org.openimaj.math.geometry.point.Point2d;
41 import org.openimaj.video.Video;
42 import org.openimaj.video.VideoFrame;
43 import org.openimaj.video.analyser.VideoAnalyser;
44 import org.openimaj.video.timecode.HrsMinSecFrameTimecode;
45
46
47 /**
48 * A motion estimator will estimate the motion of parts of a video frame.
49 * This class includes a set of algorithms for calculating the motion estimation.
50 * <p>
51 * This class deals with the buffering of frames from the video which to pass
52 * to the motion estimation. The class is abstract and the method
53 * {@link #estimateMotionField(MotionEstimatorAlgorithm, VideoFrame, VideoFrame[])}
54 * must be overridden by an implementing class to provide the field over which
55 * the motion estimation will take place. This field may, for example, be a grid
56 * or an overlapping grid. This overridden method must also determine the appropriate
57 * way to call the motion estimation algorithm while returning a map which maps
58 * a point to a displacement vector.
59 *
60 * @author David Dupplaw (dpd@ecs.soton.ac.uk)
61 * @created 1 Mar 2012
62 *
63 */
64 @SuppressWarnings( "javadoc" )
65 public abstract class MotionEstimator extends VideoAnalyser<FImage>
66 {
67 /** The estimator to use */
68 private MotionEstimatorAlgorithm estimator = null;
69
70 /** The old frame stack. It's a queue so the oldest frame is popped off */
71 private Queue<VideoFrame<FImage>> oldFrames = null;
72
73 /** The estimated motion vectors for the last analysed frame */
74 public Map<Point2d,Point2d> motionVectors = null;
75
76 /**
77 * Constructor a new motion estimator using the given algorithm.
78 * @param alg The algorithm to use to estimate motion.
79 */
80 public MotionEstimator( MotionEstimatorAlgorithm alg )
81 {
82 this.estimator = alg;
83 oldFrames = new LinkedList<VideoFrame<FImage>>();
84 }
85
86 /**
87 * Create a chainable motion estimator.
88 * @param v The video to chain to
89 * @param alg The algorithm to use to estimate motion
90 */
91 public MotionEstimator( Video<FImage> v, MotionEstimatorAlgorithm alg )
92 {
93 super(v);
94 this.estimator = alg;
95 oldFrames = new LinkedList<VideoFrame<FImage>>();
96 }
97
98 /**
99 * {@inheritDoc}
100 * @see org.openimaj.video.analyser.VideoAnalyser#analyseFrame(org.openimaj.image.Image)
101 */
102 @SuppressWarnings( "unchecked" )
103 @Override
104 public void analyseFrame( FImage frame )
105 {
106 VideoFrame<FImage> vf = new VideoFrame<FImage>( frame,
107 new HrsMinSecFrameTimecode( getTimeStamp(), getFPS() ) );
108
109 motionVectors = estimateMotionField( estimator, vf,
110 oldFrames.toArray( new VideoFrame[0] ) );
111
112 oldFrames.offer( vf );
113
114 // Make sure there's never too many frames in the queue
115 if( oldFrames.size() > estimator.requiredNumberOfFrames() )
116 oldFrames.poll();
117 }
118
119 /**
120 * Return the estimated motion vectors for the last processed frame.
121 * @return The estimated motion vectors
122 */
123 public Map<Point2d,Point2d> getMotionVectors()
124 {
125 return motionVectors;
126 }
127
128 /**
129 * This method needs to be overridden for specific layouts of motion
130 * field within the image.
131 *
132 * @param frame The current frame
133 * @param array The list of previous frames (based on the estimator)
134 * @return The motion field
135 */
136 protected abstract Map<Point2d, Point2d> estimateMotionField(
137 MotionEstimatorAlgorithm estimator, VideoFrame<FImage> frame,
138 VideoFrame<FImage>[] array );
139 }