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}