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 */ 030package org.openimaj.demos.video; 031 032import java.io.File; 033import java.io.IOException; 034import java.util.ArrayList; 035import java.util.List; 036 037import org.openimaj.image.DisplayUtilities; 038import org.openimaj.image.MBFImage; 039import org.openimaj.image.processing.transform.MBFProjectionProcessor; 040import org.openimaj.image.processing.transform.ProjectionProcessor; 041import org.openimaj.image.renderer.MBFImageRenderer; 042import org.openimaj.math.geometry.point.Point2d; 043import org.openimaj.math.geometry.point.Point2dImpl; 044import org.openimaj.math.geometry.shape.Polygon; 045import org.openimaj.math.geometry.shape.Rectangle; 046import org.openimaj.math.geometry.transforms.TransformUtilities; 047import org.openimaj.util.pair.IndependentPair; 048import org.openimaj.video.VideoDisplay; 049import org.openimaj.video.VideoDisplayListener; 050import org.openimaj.video.capture.VideoCapture; 051import org.openimaj.video.xuggle.XuggleVideo; 052 053import Jama.Matrix; 054 055public class VideoWithinVideo implements VideoDisplayListener<MBFImage> { 056 public File videoFile; 057 public XuggleVideo video; 058 public VideoCapture capture; 059 public VideoDisplay<MBFImage> display; 060 public Polygon targetArea; 061 public MBFImageRenderer renderer; 062 public List<IndependentPair<Point2d, Point2d>> pointList; 063 public Point2dImpl topLeftS = new Point2dImpl(), topLeftB = new Point2dImpl(); 064 public Point2dImpl topRightS = new Point2dImpl(), topRightB = new Point2dImpl(); 065 public Point2dImpl bottomLeftS = new Point2dImpl(), bottomLeftB = new Point2dImpl(); 066 public Point2dImpl bottomRightS = new Point2dImpl(), bottomRightB = new Point2dImpl(); 067 public Matrix captureToVideo; 068 public Rectangle videoRect; 069 private MBFImage nextCaptureFrame; 070 071 public VideoWithinVideo(String videoPath) throws IOException { 072 this.videoFile = new File(videoPath); 073 this.video = new XuggleVideo(videoFile, true); 074 this.capture = new VideoCapture(320, 240); 075 nextCaptureFrame = capture.getNextFrame().clone(); 076 077 this.videoRect = new Rectangle(0, 0, video.getWidth(), video.getHeight()); 078 this.captureToVideo = TransformUtilities.makeTransform( 079 new Rectangle(0, 0, capture.getWidth(), capture.getHeight()), 080 videoRect 081 ); 082 083 display = VideoDisplay.createVideoDisplay(video); 084 new CaptureVideoSIFT(this); 085 display.addVideoListener(this); 086 087 // targetArea = new Polygon( 088 // new Point2dImpl(100,100), 089 // new Point2dImpl(200,150), 090 // new Point2dImpl(200,230), 091 // new Point2dImpl(0,200) 092 // ); 093 // 094 095 // Prepare the homography matrix 096 pointList = new ArrayList<IndependentPair<Point2d, Point2d>>(); 097 pointList.add(IndependentPair.pair((Point2d) topLeftB, (Point2d) topLeftS)); 098 pointList.add(IndependentPair.pair((Point2d) topRightB, (Point2d) topRightS)); 099 pointList.add(IndependentPair.pair((Point2d) bottomRightB, (Point2d) bottomRightS)); 100 pointList.add(IndependentPair.pair((Point2d) bottomLeftB, (Point2d) bottomLeftS)); 101 102 } 103 104 @Override 105 public void afterUpdate(VideoDisplay<MBFImage> display) { 106 } 107 108 @Override 109 public void beforeUpdate(MBFImage frame) { 110 DisplayUtilities.displayName(frame, "video"); 111 if (renderer == null) { 112 this.renderer = frame.createRenderer(); 113 114 } 115 // this.renderer.drawShapeFilled(targetArea, RGBColour.RED); 116 updatePolygon(); 117 final ProjectionProcessor<Float[], MBFImage> proc = new MBFProjectionProcessor(); 118 proc.setMatrix(captureToVideo); 119 120 proc.accumulate(nextCaptureFrame); 121 if (this.targetArea != null) { 122 final Matrix transform = TransformUtilities.homographyMatrixNorm(pointList); 123 proc.setMatrix(transform); 124 proc.accumulate(frame.clone()); 125 } 126 synchronized (this) { 127 proc.performProjection(0, 0, frame); 128 } 129 } 130 131 public void updatePolygon() { 132 if (this.targetArea != null) { 133 final Point2dImpl stl = (Point2dImpl) targetArea.points.get(0); 134 final Point2dImpl str = (Point2dImpl) targetArea.points.get(1); 135 final Point2dImpl sbr = (Point2dImpl) targetArea.points.get(2); 136 final Point2dImpl sbl = (Point2dImpl) targetArea.points.get(3); 137 this.topLeftS.x = stl.x; 138 this.topLeftS.y = stl.y; // top left small rectangle 139 this.topRightS.x = str.x; 140 this.topRightS.y = str.y; // top right small rectangle 141 this.bottomRightS.x = sbr.x; 142 this.bottomRightS.y = sbr.y; // bottom right small rectangle 143 this.bottomLeftS.x = sbl.x; 144 this.bottomLeftS.y = sbl.y; // bottom right small rectangle 145 } 146 147 this.topLeftB.x = videoRect.x; 148 this.topLeftB.y = videoRect.y; // top left big rectangle 149 this.topRightB.x = videoRect.x + videoRect.width; 150 this.topRightB.y = videoRect.y; // top right big rectangle 151 this.bottomRightB.x = videoRect.x + videoRect.width; 152 this.bottomRightB.y = videoRect.y + videoRect.height; // bottom right 153 // big rectangle 154 this.bottomLeftB.x = videoRect.x; 155 this.bottomLeftB.y = videoRect.y + videoRect.height; // bottom right big 156 // rectangle 157 } 158 159 public static void main(String[] args) throws IOException { 160 new VideoWithinVideo("/Users/jsh2/Movies/Screen Recording.mov"); 161 } 162 163 public synchronized void copyToCaptureFrame(MBFImage frameWrite) { 164 this.nextCaptureFrame.internalCopy(frameWrite); 165 } 166}