001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030/**
031 *
032 */
033package org.openimaj.video.processing.motion;
034
035import java.util.HashMap;
036import java.util.Map;
037
038import org.openimaj.image.FImage;
039import org.openimaj.math.geometry.point.Point2d;
040import org.openimaj.math.geometry.point.Point2dImpl;
041import org.openimaj.math.geometry.shape.Rectangle;
042import org.openimaj.video.Video;
043import org.openimaj.video.VideoFrame;
044import org.openimaj.video.VideoSubFrame;
045
046/**
047 *      Estimates the motion field over a grid.
048 *
049 *      @author David Dupplaw (dpd@ecs.soton.ac.uk)
050 *  @created 1 Mar 2012
051 *
052 */
053public class GridMotionEstimator extends MotionEstimator
054{
055        private int x, y;
056        private boolean fixed;
057
058        /**
059         *      Construct a grid-based motion estimator. If <code>fixed</code> is
060         *      true, the x and y values represent the width and height of the pixel
061         *      blocks. If <code>fixed</code> is false, the x and y represent the number
062         *      of grid elements to spread evenly across the frame.
063         *
064         *      @param alg The estimator algorithm to use
065         *      @param x The x value
066         *      @param y The y value
067         *      @param fixed Whether x and y represent pixels or grid count.
068         */
069        public GridMotionEstimator( MotionEstimatorAlgorithm alg,
070                        int x, int y, boolean fixed )
071        {
072                super( alg );
073                this.x = x; this.y = y;
074                this.fixed = fixed;
075        }
076
077        /**
078         *      Construct a chained grid-based motion estimator. If <code>fixed</code> is
079         *      true, the x and y values represent the width and height of the pixel
080         *      blocks. If <code>fixed</code> is false, the x and y represent the number
081         *      of grid elements to spread evenly across the frame.
082         *
083         *      @param v The video to chain to
084         *      @param alg The estimator algorithm to use
085         *      @param x The x value
086         *      @param y The y value
087         *      @param fixed Whether x and y represent pixels or grid count.
088         */
089        public GridMotionEstimator( Video<FImage> v, MotionEstimatorAlgorithm alg,
090                        int x, int y, boolean fixed )
091        {
092                super( v, alg );
093                this.x = x; this.y = y;
094                this.fixed = fixed;
095        }
096
097        /**
098         *      {@inheritDoc}
099         *      @see org.openimaj.video.analysis.motion.MotionEstimator#estimateMotionField(org.openimaj.video.analysis.motion.MotionEstimator.MotionEstimatorAlgorithm, org.openimaj.image.FImage, org.openimaj.image.FImage[])
100         */
101        @Override
102        protected Map<Point2d, Point2d> estimateMotionField(
103                        MotionEstimatorAlgorithm estimator, VideoFrame<FImage> vf,
104                        VideoFrame<FImage>[] array )
105        {
106                if( array.length < 1 )
107                        return new HashMap<Point2d,Point2d>();
108
109                int gw = 0, gh = 0;
110                if( fixed )
111                {
112                        gw = x;
113                        gh = y;
114                }
115                else
116                {
117                        gw = vf.frame.getWidth()/x;
118                        gh = vf.frame.getHeight()/y;
119                }
120
121                Map<Point2d,Point2d> out = new HashMap<Point2d, Point2d>();
122
123                @SuppressWarnings( "unchecked" )
124                VideoSubFrame<FImage>[] otherFrames = new VideoSubFrame[array.length];
125
126                for( int yy = 0; yy < vf.frame.getHeight(); yy += gh )
127                {
128                        for( int xx = 0; xx < vf.frame.getWidth(); xx += gw )
129                        {
130                                for( int ff = 0; ff < array.length; ff++ )
131                                        otherFrames[ff] = new VideoSubFrame<FImage>(
132                                                        array[ff].frame,
133                                                        array[ff].timecode,
134                                                        new Rectangle(xx, yy, gw, gh));
135
136                                // vf.frame.drawShape( new Rectangle(xx,yy,gw,gh), 1, 0f );
137
138                                out.put( new Point2dImpl(xx+gw/2f,yy+gh/2f),
139                                                estimator.estimateMotion( new VideoSubFrame<FImage>(
140                                                        vf.frame,
141                                                        vf.timecode,
142                                                        new Rectangle(xx, yy, gw, gh)),
143                                                        otherFrames ) );
144                        }
145                }
146
147                return out;
148        }
149}