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.hardware.kinect; 031 032import java.nio.ByteBuffer; 033 034import org.bridj.Pointer; 035import org.openimaj.hardware.kinect.freenect.libfreenectLibrary; 036import org.openimaj.hardware.kinect.freenect.libfreenectLibrary.freenect_depth_cb; 037import org.openimaj.hardware.kinect.freenect.libfreenectLibrary.freenect_depth_format; 038import org.openimaj.hardware.kinect.freenect.libfreenectLibrary.freenect_device; 039import org.openimaj.hardware.kinect.freenect.libfreenectLibrary.freenect_resolution; 040import org.openimaj.image.FImage; 041 042/** 043 * Callback handling the depth information 044 * 045 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 046 * 047 */ 048class DepthCallback extends freenect_depth_cb implements KinectStreamCallback { 049 private static final float[] LUT = new float[2048]; 050 static { 051 for (int i = 0; i < LUT.length; i++) 052 LUT[i] = i / (LUT.length - 1f); 053 } 054 055 KinectDepthStream stream; 056 ByteBuffer buffer; 057 int nextTimeStamp; 058 FImage nextFrame; 059 boolean updated = false; 060 061 public DepthCallback(KinectDepthStream stream, boolean registeredDepthMode) { 062 this.stream = stream; 063 final Pointer<freenect_device> device = stream.controller.device; 064 065 if (registeredDepthMode) 066 libfreenectLibrary.freenect_set_depth_mode_proxy(device, freenect_resolution.FREENECT_RESOLUTION_MEDIUM, 067 freenect_depth_format.FREENECT_DEPTH_REGISTERED); 068 else 069 libfreenectLibrary.freenect_set_depth_mode_proxy(device, freenect_resolution.FREENECT_RESOLUTION_MEDIUM, 070 freenect_depth_format.FREENECT_DEPTH_11BIT); 071 072 buffer = ByteBuffer.allocateDirect(libfreenectLibrary.freenect_get_video_buffer_size(device)); 073 libfreenectLibrary.freenect_set_depth_buffer(device, Pointer.pointerToBuffer(buffer)); 074 075 nextFrame = new FImage(stream.width, stream.height); 076 077 libfreenectLibrary.freenect_set_depth_callback(device, toPointer()); 078 libfreenectLibrary.freenect_start_depth(device); 079 } 080 081 @Override 082 public synchronized void apply(Pointer<freenect_device> dev, Pointer<?> depth, int timestamp) { 083 updated = true; 084 nextTimeStamp = timestamp; 085 086 setImage(); 087 } 088 089 @Override 090 public synchronized void swapFrames() { 091 if (!updated) 092 return; 093 094 final FImage tmp = stream.frame; 095 stream.frame = nextFrame; 096 nextFrame = tmp; 097 stream.timeStamp = nextTimeStamp; 098 updated = false; 099 } 100 101 public void setImage() { 102 final ByteBuffer buf = buffer.duplicate(); 103 104 final int width = stream.width; 105 final int height = stream.height; 106 107 final float[][] pix = nextFrame.pixels; 108 109 for (int y = 0; y < height; y++) { 110 for (int x = 0; x < width; x++) { 111 final int first = (buf.get() & 0xFF); 112 final int second = (buf.get() & 0xFF); 113 pix[y][x] = first + (second << 8); 114 } 115 } 116 } 117 118 @Override 119 public void stop() { 120 libfreenectLibrary.freenect_stop_depth(stream.controller.device); 121 } 122} 123 124/** 125 * The stream of depth information 126 * 127 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 128 * 129 */ 130public class KinectDepthStream extends KinectStream<FImage> { 131 boolean registered; 132 133 /** 134 * Construct with a reference to the controller 135 * 136 * @param controller 137 * The controller 138 * @param registeredDepthMode 139 * whether to register the depth image. If true, depth 140 * measurements are in millimeters. 141 */ 142 public KinectDepthStream(KinectController controller, boolean registeredDepthMode) { 143 super(controller); 144 145 fps = 30; 146 width = 640; 147 height = 480; 148 frame = new FImage(width, height); 149 registered = registeredDepthMode; 150 151 callback = new DepthCallback(this, registeredDepthMode); 152 } 153}