Java tutorial
import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.nio.ByteBuffer; import java.nio.ShortBuffer; import java.text.DecimalFormat; import javax.swing.JPanel; import org.OpenNI.AlternativeViewpointCapability; import org.OpenNI.Context; import org.OpenNI.DepthGenerator; import org.OpenNI.DepthMetaData; import org.OpenNI.GeneralException; import org.OpenNI.ImageGenerator; import org.OpenNI.License; import org.OpenNI.MapOutputMode; import org.OpenNI.PixelFormat; import org.OpenNI.SceneMetaData; import org.OpenNI.StatusException; import org.OpenNI.UserGenerator; import org.json.simple.parser.ParseException; public class TrackerPanel extends JPanel implements Runnable, GesturesWatcher { private static final long serialVersionUID = 1L; private BufferedImage cameraImage; private int[] cameraPixels; private int hideBGPixel; private static final int MAX_DEPTH_SIZE = 10000; private Color USER_COLORS[] = { Color.RED, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA, Color.PINK, Color.YELLOW, Color.WHITE }; /* * colors used to draw each user's depth image, except the last (white) * which is for the background */ private byte[] imgbytes; private int imWidth, imHeight; private float histogram[]; // for the depth values private int maxDepth = 0; // largest depth value private volatile boolean isRunning; // used for the average ms processing information private int imageCount = 0; private long totalTime = 0; private DecimalFormat df; private Font msgFont; // OpenNI private Context context; private DepthMetaData depthMD; private DepthGenerator depthGen; private ImageGenerator imageGen; private SceneMetaData sceneMD; private Skeletons skels; // the users' skeletons public TrackerPanel() { setBackground(Color.GRAY); df = new DecimalFormat("0.#"); // 1 dp msgFont = new Font("SansSerif", Font.BOLD, 13); configOpenNI(); histogram = new float[MAX_DEPTH_SIZE]; imWidth = depthMD.getFullXRes(); imHeight = depthMD.getFullYRes(); setSize(imWidth * 2, imHeight); System.out.println("Image dimensions (" + imWidth + ", " + imHeight + ")"); // create empty image bytes array of correct size and type imgbytes = new byte[imWidth * imHeight * 3]; hideBGPixel = new Color(0, 0, 255, 0).getRGB(); // create d.s for holding camera pixels and image cameraPixels = new int[imWidth * imHeight]; cameraImage = new BufferedImage(imWidth, imHeight, BufferedImage.TYPE_INT_ARGB); // the image must have an alpha channel for the transparent blue pixels new Thread(this).start(); // start updating the panel } // end of TrackerPanel() private void configOpenNI() { try { context = new Context(); License license = new License("PrimeSense", "0KOIk2JeIBYClPWVnMoRKn5cdY4="); context.addLicense(license); depthGen = DepthGenerator.create(context); imageGen = ImageGenerator.create(context); // set the viewpoint of the DepthGenerator to match the // ImageGenerator AlternativeViewpointCapability altViewCap = depthGen.getAlternativeViewpointCapability(); altViewCap.setViewpoint(imageGen); MapOutputMode mapMode = new MapOutputMode(640, 480, 30); depthGen.setMapOutputMode(mapMode); imageGen.setMapOutputMode(mapMode); imageGen.setPixelFormat(PixelFormat.RGB24); context.setGlobalMirror(true); // set mirror mode depthMD = depthGen.getMetaData(); UserGenerator userGen = UserGenerator.create(context); sceneMD = userGen.getUserPixels(0); skels = new Skeletons(userGen, depthGen, this); context.startGeneratingAll(); System.out.println("Started context generating..."); } catch (Exception e) { System.out.println(e); System.exit(1); } } public Dimension getPreferredSize() { return new Dimension(imWidth, imHeight); } public void closeDown() { isRunning = false; } public void run() { isRunning = true; while (isRunning) { try { context.waitAnyUpdateAll(); } catch (StatusException e) { System.out.println(e); System.exit(1); } long startTime = System.currentTimeMillis(); screenUsers(); updateUserDepths(); skels.update(); screenUsers(); imageCount++; totalTime += (System.currentTimeMillis() - startTime); repaint(); } // close down try { context.stopGeneratingAll(); } catch (StatusException e) { } context.release(); System.exit(0); } // end of run() private void screenUsers() { // store the Kinect RGB image as a pixel array in cameraPixels try { ByteBuffer imageBB = imageGen.getImageMap().createByteBuffer(); convertToPixels(imageBB, cameraPixels); } catch (GeneralException e) { System.out.println(e); } hideBackground(cameraPixels); // change the modified pixels into an image cameraImage.setRGB(0, 0, imWidth, imHeight, cameraPixels, 0, imWidth); imageCount++; } // end of screenUsers() private void convertToPixels(ByteBuffer pixelsRGB, int[] cameraPixels) { int rowStart = 0; int bbIdx; // index into ByteBuffer int i = 0; // index into pixels int[] int rowLen = imWidth * 3; // number of bytes in each row for (int row = 0; row < imHeight; row++) { bbIdx = rowStart; // System.out.println("bbIdx: " + bbIdx); for (int col = 0; col < imWidth; col++) { int pixR = pixelsRGB.get(bbIdx++); int pixG = pixelsRGB.get(bbIdx++); int pixB = pixelsRGB.get(bbIdx++); cameraPixels[i++] = 0xFF000000 | ((pixR & 0xFF) << 16) | ((pixG & 0xFF) << 8) | (pixB & 0xFF); } rowStart += rowLen; // move to next row } } // end of convertToPixels() private void hideBackground(int[] cameraPixels) { depthMD = depthGen.getMetaData(); ShortBuffer usersBuf = sceneMD.getData().createShortBuffer(); int userCount = 0; int maxUserCount = 0; int userCountMaxRow = 0; int maxY = 0; int row = 0; int rowCount = 0; while (usersBuf.remaining() > 0) { int pos = usersBuf.position(); short userID = usersBuf.get(); if (userID == 0) { // if not a user (i.e. is part of the background) cameraPixels[pos] = hideBGPixel; // make pixel transparent } else { userCount++; int y = imHeight - row; if (y > maxY) { maxY = y; } } rowCount++; if (rowCount == imWidth) { if (userCount > maxUserCount) { maxUserCount = userCount; userCountMaxRow = row; } row++; rowCount = 0; userCount = 0; } } int startPoint = imWidth * (imHeight - maxY); int finalPoint = startPoint + imWidth; if (maxY != 0) { printLine(startPoint, finalPoint, Color.YELLOW.getRGB()); } startPoint = imWidth * (userCountMaxRow); finalPoint = startPoint + imWidth; if (userCountMaxRow != 0) { SimpleHTTPPOSTRequester httpPost = new SimpleHTTPPOSTRequester(); try { httpPost.makeHTTPPOSTRequest(userCountMaxRow); } catch (ParseException e1) { e1.printStackTrace(); } Util.insertLastPoint(userCountMaxRow); int response = Util.analyzeLastFivePoints(); if (response == Util.NOT_READY) { printLine(startPoint, finalPoint, Color.RED.getRGB()); } else if (response == Util.READY) { printLine(startPoint, finalPoint, Color.WHITE.getRGB()); } else if (response == Util.GOING_UP) { printLine(startPoint, finalPoint, Color.GREEN.getRGB()); } else if (response == Util.GOING_DOWN) { printLine(startPoint, finalPoint, Color.PINK.getRGB()); } } } private void printLine(int startPoint, int finalPoint, int rgbColor) { for (int i = startPoint; i < finalPoint; i++) { cameraPixels[i] = rgbColor; } } private void updateUserDepths() { depthMD = depthGen.getMetaData(); ShortBuffer depthBuf = depthMD.getData().createShortBuffer(); calcHistogram(depthBuf); depthBuf.rewind(); ShortBuffer usersBuf = sceneMD.getData().createShortBuffer(); while (depthBuf.remaining() > 0) { int pos = depthBuf.position(); short depthVal = depthBuf.get(); short userID = usersBuf.get(); imgbytes[3 * pos] = 0; // default colour is black when there's no // depth data imgbytes[3 * pos + 1] = 0; imgbytes[3 * pos + 2] = 0; if (depthVal != 0) { // there is depth data // convert userID to index into USER_COLORS[] int colorIdx = userID % (USER_COLORS.length - 1); // skip last // color if (userID == 0) // not a user; actually the background colorIdx = USER_COLORS.length - 1; // use last index: the position of white in USER_COLORS[] // convert histogram value (0.0-1.0f) to a RGB color float histValue = histogram[depthVal]; imgbytes[3 * pos] = (byte) (histValue * USER_COLORS[colorIdx].getRed()); imgbytes[3 * pos + 1] = (byte) (histValue * USER_COLORS[colorIdx].getGreen()); imgbytes[3 * pos + 2] = (byte) (histValue * USER_COLORS[colorIdx].getBlue()); } } } private void calcHistogram(ShortBuffer depthBuf) { // reset histogram for (int i = 0; i <= maxDepth; i++) histogram[i] = 0; // record number of different depths in histogram[] int numPoints = 0; maxDepth = 0; while (depthBuf.remaining() > 0) { short depthVal = depthBuf.get(); if (depthVal > maxDepth) maxDepth = depthVal; if ((depthVal != 0) && (depthVal < MAX_DEPTH_SIZE)) { // skip // histogram[0] histogram[depthVal]++; numPoints++; } } // System.out.println("No. of numPoints: " + numPoints); // System.out.println("Maximum depth: " + maxDepth); // convert into a cummulative depth count (skipping histogram[0]) for (int i = 1; i <= maxDepth; i++) histogram[i] += histogram[i - 1]; /* * convert cummulative depth into the range 0.0 - 1.0f which will later * be used to modify a color from USER_COLORS[] */ if (numPoints > 0) { for (int i = 1; i <= maxDepth; i++) // skipping histogram[0] histogram[i] = 1.0f - (histogram[i] / (float) numPoints); } } // end of calcHistogram() // -------------------- drawing ------------------------- public void paintComponent(Graphics g) // Draw the depth image with coloured users, skeletons, and statistics info { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; drawUserDepths(g2d); g2d.drawImage(cameraImage, 641, 0, this); g2d.setFont(msgFont); // for user status and stats skels.draw(g2d); writeStats(g2d); } // end of paintComponent() private void drawUserDepths(Graphics2D g2d) { // define an 8-bit RGB channel color model ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8 }, false, false, ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE); // fill the raster with the depth image bytes DataBufferByte dataBuffer = new DataBufferByte(imgbytes, imWidth * imHeight * 3); WritableRaster raster = Raster.createInterleavedRaster(dataBuffer, imWidth, imHeight, imWidth * 3, 3, new int[] { 0, 1, 2 }, null); // combine color model and raster to create a BufferedImage BufferedImage image = new BufferedImage(colorModel, raster, false, null); g2d.drawImage(image, 0, 0, null); } // end of drawUserDepths() private void writeStats(Graphics2D g2d) { g2d.setColor(Color.WHITE); int panelHeight = getHeight(); if (imageCount > 0) { double avgGrabTime = (double) totalTime / imageCount; g2d.drawString("Pic " + imageCount + " " + df.format(avgGrabTime) + " ms", 5, panelHeight); // bottom left } else // no image yet g2d.drawString("Loading...", 5, panelHeight); } // ------------GesturesWatcher.pose() ----------------------------- public void pose(int userID, GestureName gest, boolean isActivated) // called by the gesture detectors { // if (isActivated) //System.out.println(gest + " " + userID + " on"); } // end of pose() } // end of TrackerPanel class