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.awt.GraphicsDevice; 033import java.awt.GraphicsEnvironment; 034import java.awt.Toolkit; 035import java.awt.event.KeyEvent; 036import java.awt.event.KeyListener; 037import java.util.LinkedList; 038import java.util.Queue; 039import javax.swing.JFrame; 040import javax.swing.SwingUtilities; 041 042import org.openimaj.demos.Demo; 043import org.openimaj.hardware.kinect.KinectController; 044import org.openimaj.hardware.kinect.KinectException; 045import org.openimaj.image.DisplayUtilities; 046import org.openimaj.image.FImage; 047import org.openimaj.image.MBFImage; 048import org.openimaj.image.processing.resize.ResizeProcessor; 049import org.openimaj.util.pair.IndependentPair; 050import org.openimaj.video.Video; 051import org.openimaj.video.VideoDisplay; 052 053 054/** 055 * Kinect integration demo. Shows video and depth. Press t to toggle between 056 * rgb and ir mode. Pressing w and x moves the device up or down. 057 * Pressing s levels the device. 058 * 059 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 060 */ 061@Demo( 062 author = "Jonathon Hare", 063 description = "Kinect integration demo. Shows video and depth. Press t " + 064 "to toggle between rgb and ir mode. Pressing w and x moves the device " + 065 "up or down. Pressing s levels the device.", 066 keywords = { "kinect", "video" }, 067 title = "Kinect Integration", 068 screenshot = "/org/openimaj/demos/screens/hardware/kinect.png", 069 icon = "/org/openimaj/demos/icons/hardware/kinect.png" 070) 071public class KinectDepthSnapshot extends Video<MBFImage> implements KeyListener { 072 private static final int MAX_HELD_FRAMES = 10; 073 MBFImage currentFrame; 074 KinectController controller; 075 JFrame frame; 076 private double tilt = 0; 077 private boolean irmode = false; 078 private VideoDisplay<MBFImage> videoFrame; 079 private Queue<IndependentPair<FImage, MBFImage>> heldDepthFrames; 080 private IndependentPair<FImage, MBFImage> currentDepthFrame; 081 private int screenWidth; 082 private int screenHeight; 083 protected ResizeProcessor fullScreenResizeProcessor; 084 085 /** 086 * Default constructor 087 * @param id of kinect controller 088 * @throws KinectException 089 */ 090 public KinectDepthSnapshot(int id) throws KinectException { 091 controller = new KinectController(id, irmode,true); 092 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 093 GraphicsDevice[] devices = ge.getScreenDevices(); 094 JFrame frame=new JFrame("Full Screen JFrame"); 095 //Set default close operation for JFrame 096 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 097 //Set JFrame size to full screen size follow current screen size 098 screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width; 099 screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height; 100 fullScreenResizeProcessor = new ResizeProcessor(screenWidth, screenHeight); 101 frame.setBounds(0,0,screenWidth,screenHeight); 102 videoFrame = VideoDisplay.createVideoDisplay(this, new DisplayUtilities.ImageComponent(true)); 103 JFrame wholeWindow = new JFrame(); 104 wholeWindow.setUndecorated(true); 105 wholeWindow.setAlwaysOnTop(true); 106 wholeWindow.getContentPane().add(videoFrame.getScreen()); 107 devices[0].setFullScreenWindow(wholeWindow); 108 ((JFrame)SwingUtilities.getRoot(videoFrame.getScreen())).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 109 SwingUtilities.getRoot(videoFrame.getScreen()).addKeyListener(this); 110 111 } 112 113 @Override 114 public MBFImage getNextFrame() { 115 FImage tmp = controller.depthStream.getNextFrame(); 116 MBFImage frame = (MBFImage) controller.videoStream.getNextFrame();//Transforms.Grey_To_Colour((FImage) tmp); 117 118// depth.bands.get(0).shiftRightInplace(50); 119// depth.bands.get(1).shiftRightInplace(50); 120// depth.bands.get(2).shiftRightInplace(50); 121 122// MBFImage depth = ((FImage) controller.videoStream.getNextFrame()).toRGB(); 123 124// // Clean Frames 125// if (currentFrame == null || super.currentFrame % 600 == 0) 126// { 127// currentFrame = frame.clone(); 128// } 129// 130// if(oldDepth == null || super.currentFrame % 600 == 0) 131// { 132// oldDepth = tmp.clone(); 133// } 134 135 // Update held depths 136 if(super.currentFrame % 30 == 0){ 137 if (super.currentFrame % (60 * 2 * MAX_HELD_FRAMES) == 0) 138 { 139 removeAllFrames(); 140 } 141 142 addDepthFrame(tmp,frame); 143 currentFrame = this.currentDepthFrame.secondObject(); 144 } 145 else{ 146 FImage oldDepth = this.currentDepthFrame.firstObject().clone(); 147 currentFrame = this.currentDepthFrame.secondObject().clone(); 148 for (int y = 0; y < tmp.height; y++) { 149 for (int x = 0; x < tmp.width; x++) { 150 if (oldDepth.pixels[y][x] == 0 || (tmp.pixels[y][x] != 0 && oldDepth.pixels[y][x] > tmp.pixels[y][x])) { 151// oldDepth.pixels[y][x] = tmp.pixels[y][x]; 152 currentFrame.setPixel(x, y, frame.getPixel(x, y)); 153 } 154 } 155 } 156 } 157 158 super.currentFrame++; 159// return currentFrame.process(fullScreenResizeProcessor); 160 return currentFrame; 161 } 162 163 private void removeAllFrames() { 164 if (this.heldDepthFrames!=null)this.heldDepthFrames.clear(); 165 } 166 167 private void addDepthFrame(FImage tmp, MBFImage frame) { 168 if(this.heldDepthFrames == null){ 169 this.heldDepthFrames = new LinkedList<IndependentPair<FImage,MBFImage>>(); 170 } 171 if(this.heldDepthFrames.size() == MAX_HELD_FRAMES){ 172 this.heldDepthFrames.poll(); 173 } 174 175 176 this.heldDepthFrames.add(IndependentPair.pair(tmp.clone(), frame.clone())); 177 System.out.println("Added frame, new frame size:" + this.heldDepthFrames.size()); 178 this.currentDepthFrame = constructDepthFrame(); 179 } 180 181 private IndependentPair<FImage, MBFImage> constructDepthFrame() { 182 FImage compiledDepth = null; 183 MBFImage compiledRGB = null; 184 for (IndependentPair<FImage, MBFImage> heldFrame : this.heldDepthFrames) { 185 186 FImage heldDepth = heldFrame.firstObject(); 187 MBFImage heldRGB = heldFrame.secondObject(); 188 if(compiledDepth == null){ 189 190 compiledDepth = heldDepth.clone(); 191 compiledRGB = heldRGB .clone(); 192 continue; 193 } 194 195 for (int y = 0; y < heldDepth.height; y++) { 196 for (int x = 0; x < heldDepth.width; x++) { 197 if (compiledDepth.pixels[y][x] == 0 || (heldDepth.pixels[y][x] != 0 && compiledDepth.pixels[y][x] > heldDepth.pixels[y][x])) { 198 compiledDepth.pixels[y][x] = heldDepth.pixels[y][x]; 199 compiledRGB.setPixel(x, y, heldRGB.getPixel(x, y)); 200 } 201 } 202 } 203 } 204 return IndependentPair.pair(compiledDepth, compiledRGB); 205 } 206 207 @Override 208 public MBFImage getCurrentFrame() { 209 return currentFrame; 210 } 211 212 @Override 213 public int getWidth() { 214 return this.screenWidth; 215 } 216 217 @Override 218 public int getHeight() { 219 return this.screenHeight; 220 } 221 222 @Override 223 public boolean hasNextFrame() { 224 return true; 225 } 226 227 @Override 228 public long countFrames() { 229 return -1; 230 } 231 232 @Override 233 public void reset() { 234 //do nothing 235 } 236 237 @Override 238 public void keyTyped(KeyEvent e) { 239 240 } 241 242 @Override 243 public void keyPressed(KeyEvent e) { 244 if (e.getKeyChar() == 'w') { 245 controller.setTilt(tilt+=1); 246 } else if (e.getKeyChar() == 'x') { 247 controller.setTilt(tilt-=1); 248 } else if (e.getKeyChar() == 's') { 249 controller.setTilt(tilt=0); 250 } else if (e.getKeyChar() == 't') { 251 controller.setIRMode(irmode=!irmode ); 252 } 253 } 254 255 @Override 256 public void keyReleased(KeyEvent e) { 257 258 } 259 260 /** 261 * Default main 262 * @param args Command-line arguments 263 * @throws KinectException 264 */ 265 public static void main(String[] args) throws KinectException { 266 new KinectDepthSnapshot(0); 267 } 268 269 @Override 270 public long getTimeStamp() 271 { 272 return (long)(super.currentFrame * 1000 / getFPS()); 273 } 274 275 @Override 276 public double getFPS() 277 { 278 return 30; 279 } 280 281 /** 282 * Get the display showing the kinect video 283 * @return The video display 284 */ 285 public VideoDisplay<MBFImage> getDisplay() { 286 return videoFrame; 287 } 288}