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.shotdetector; 034 035import org.openimaj.feature.DoubleFVComparison; 036import org.openimaj.image.MBFImage; 037import org.openimaj.image.analysis.algorithm.histogram.HistogramAnalyser; 038import org.openimaj.math.statistics.distribution.Histogram; 039import org.openimaj.video.Video; 040 041/** 042 * Video shot detector class implemented as a video display listener. This 043 * means that shots can be detected as the video plays. The class also 044 * supports direct processing of a video file (with no display). The default 045 * shot boundary threshold is 5000 which is an unnormalised value and will 046 * depend on the frame size. 047 * <p> 048 * Only the last keyframe is stored during processing, so if you want to store 049 * a list of keyframes you must store this list yourself by listening to the 050 * ShotDetected event which provides a VideoKeyframe which has a timecode 051 * and an image. Each event will receive the same VideoKeyframe instance 052 * containing different information. USe VideoKeyframe#clone() to make a copy. 053 * 054 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 055 * 056 * @created 1 Jun 2011 057 */ 058public class HistogramVideoShotDetector 059 extends VideoShotDetector<MBFImage> 060{ 061 /** The previous frame's histogram */ 062 private Histogram lastHistogram; 063 064 /** 065 * If you use this constructor, your timecodes will be messed up 066 * unless you call {@link #setFPS(double)} before you process 067 * any frames. 068 */ 069 public HistogramVideoShotDetector() 070 { 071 this.threshold = 5000; 072 } 073 074 /** 075 * Constructor that takes the frame rate of the source material. 076 * @param fps The FPS 077 */ 078 public HistogramVideoShotDetector( final double fps ) 079 { 080 super( fps ); 081 this.threshold = 5000; 082 } 083 084 /** 085 * Default constructor takes the video to process. 086 * @param video The video 087 */ 088 public HistogramVideoShotDetector( final Video<MBFImage> video ) 089 { 090 super( video ); 091 this.threshold = 5000; 092 } 093 094 /** 095 * Constructor that determines whether to display the processing. 096 * @param video The video 097 * @param display Whether to display the video while processing 098 */ 099 public HistogramVideoShotDetector( final Video<MBFImage> video, final boolean display ) 100 { 101 super( video, display ); 102 this.threshold = 5000; 103 } 104 105 /** 106 * Checks whether a shot boundary occurred between the given frame 107 * and the previous frame, and if so, it will add a shot boundary 108 * to the shot boundary list. 109 * 110 * @param frame The new frame to process. 111 */ 112 @Override 113 protected double getInterframeDistance( final MBFImage frame ) 114 { 115 // Get the histogram for the frame. 116 final HistogramAnalyser hp = new HistogramAnalyser( 64 ); 117 if( frame instanceof MBFImage ) 118 hp.analyseImage( frame.getBand(0) ); 119 final Histogram newHisto = hp.getHistogram(); 120 121 double dist = 0; 122 123 // If we have a last histogram, compare against it. 124 if( this.lastHistogram != null ) 125 dist = newHisto.compare( this.lastHistogram, DoubleFVComparison.EUCLIDEAN ); 126 127 this.lastHistogram = newHisto; 128 129 return dist; 130 } 131}