View Javadoc

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  package org.openimaj.demos.video;
31  
32  import java.io.File;
33  import java.io.IOException;
34  import java.util.ArrayList;
35  import java.util.List;
36  
37  import org.openimaj.image.DisplayUtilities;
38  import org.openimaj.image.MBFImage;
39  import org.openimaj.image.processing.transform.MBFProjectionProcessor;
40  import org.openimaj.image.processing.transform.ProjectionProcessor;
41  import org.openimaj.image.renderer.MBFImageRenderer;
42  import org.openimaj.math.geometry.point.Point2d;
43  import org.openimaj.math.geometry.point.Point2dImpl;
44  import org.openimaj.math.geometry.shape.Polygon;
45  import org.openimaj.math.geometry.shape.Rectangle;
46  import org.openimaj.math.geometry.transforms.TransformUtilities;
47  import org.openimaj.util.pair.IndependentPair;
48  import org.openimaj.video.VideoDisplay;
49  import org.openimaj.video.VideoDisplayListener;
50  import org.openimaj.video.capture.VideoCapture;
51  import org.openimaj.video.xuggle.XuggleVideo;
52  
53  import Jama.Matrix;
54  
55  public class VideoWithinVideo implements VideoDisplayListener<MBFImage> {
56  	public File videoFile;
57  	public XuggleVideo video;
58  	public VideoCapture capture;
59  	public VideoDisplay<MBFImage> display;
60  	public Polygon targetArea;
61  	public MBFImageRenderer renderer;
62  	public List<IndependentPair<Point2d, Point2d>> pointList;
63  	public Point2dImpl topLeftS = new Point2dImpl(), topLeftB = new Point2dImpl();
64  	public Point2dImpl topRightS = new Point2dImpl(), topRightB = new Point2dImpl();
65  	public Point2dImpl bottomLeftS = new Point2dImpl(), bottomLeftB = new Point2dImpl();
66  	public Point2dImpl bottomRightS = new Point2dImpl(), bottomRightB = new Point2dImpl();
67  	public Matrix captureToVideo;
68  	public Rectangle videoRect;
69  	private MBFImage nextCaptureFrame;
70  
71  	public VideoWithinVideo(String videoPath) throws IOException {
72  		this.videoFile = new File(videoPath);
73  		this.video = new XuggleVideo(videoFile, true);
74  		this.capture = new VideoCapture(320, 240);
75  		nextCaptureFrame = capture.getNextFrame().clone();
76  
77  		this.videoRect = new Rectangle(0, 0, video.getWidth(), video.getHeight());
78  		this.captureToVideo = TransformUtilities.makeTransform(
79  				new Rectangle(0, 0, capture.getWidth(), capture.getHeight()),
80  				videoRect
81  				);
82  
83  		display = VideoDisplay.createVideoDisplay(video);
84  		new CaptureVideoSIFT(this);
85  		display.addVideoListener(this);
86  
87  		// targetArea = new Polygon(
88  		// new Point2dImpl(100,100),
89  		// new Point2dImpl(200,150),
90  		// new Point2dImpl(200,230),
91  		// new Point2dImpl(0,200)
92  		// );
93  		//
94  
95  		// Prepare the homography matrix
96  		pointList = new ArrayList<IndependentPair<Point2d, Point2d>>();
97  		pointList.add(IndependentPair.pair((Point2d) topLeftB, (Point2d) topLeftS));
98  		pointList.add(IndependentPair.pair((Point2d) topRightB, (Point2d) topRightS));
99  		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 }