⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bandsanalyzer.java

📁 Pro Java 6 3D Game Development书中的源代码。本实例为ARMS
💻 JAVA
字号:

// BandsAnalyzer.java
// Andrew Davison, October 2005, ad@fivedots.coe.psu.ac.th

/* A thread is started which uses a JMFCapture object to take 
   a picture every SNAP_INTERVAL ms. Each image is analyzed by
   analyzeImage() to generate translation/rotation information. 
 
   The webcam picture should include a coloured
   strap around the user's wrist. The strap should contain 
   several rectangular colour bands,
   whose colours are defined as constants in this class
   (in BAND1, BAND2, etc.).

   The image is processed as an ARGB pixel array. Each pixel is
   compared to the predefined band colours, and if the pixel 
   colour is near to one of them then the pixel's coordinate is 
   added to a 'blob' for that band colour.

   Each band colour has a BandManager which maintains a series
   of 'blobs' -- a blob is a collection of localised pixel coordinates
   which all have the same colour. A pixel is added to a blob
   based on its (x,y) coordinate in the picture. If there isn't a
   nearby existing blob, then a new one is started.

   When a blob grows large enough, the image processing stops.
   The large blob info (its colour and center point)
   is converted by applyBigBlob() into rotation and translation 
   information.

   Each analyzed image is drawn into a JPanel, by calling 
   BandsPanel's showImage() method from run().
*/

import java.awt.*;
import java.awt.image.*;


public class BandsAnalyzer extends Thread
{
  private static final int SNAP_INTERVAL = 120;  // ms; the time between snaps
     /* The value for SNAP_INTERVAL is based on timings that show that a 
        snap takes about 30ms to be carried out, and the subsequent
        analysis of the image requires about 60 ms, for a total
        processing time of about 90 ms.
     */

  private static final int NUM_BANDS = 3;   // must match no. of bands colours

  /* Band colours -- modify to suit your wrist strap, the camera's
     properties, and environmental issues such as lighting and the
     background. */
  private static final Color BAND1 = new Color(205, 16, 80);   // red (1st vers)
  private static final Color BAND2 = new Color(200, 200, 85);  // yellow
  private static final Color BAND3 = new Color(50, 150, 200);  // blue
  // private static final Color BAND4 = new Color(175, 60, 65);   // red (2nd vers)

  private static final int WHITE = 0xffffff;  // pixel white

  // min. distance for blob center to move to trigger a translation
  private static final int MIN_MOVE_DIST = 10;


  private JMFCapture camera;  // JMF webcam object
  private int imSize;   // size of captured image
  private BandsPanel bandsPanel;        
            // for displaying the snapped (and modified) images

  private BandManager bandMans[];    // band managers for the bands

  // band manager and blob indicies identifying the large blob
  private int bandIdx, blobIdx;

  private Point prevCenterPt = null;   // center of blob in previous image
  private boolean running, movingFwd;



  public BandsAnalyzer(BandsPanel bp, int sz)
  {
    bandsPanel = bp;
    imSize = sz;
    bandMans = new BandManager[NUM_BANDS];

    // initialize the band managers; there should be NUM_BANDS of them
    bandMans[0] = new BandManager("red1", BAND1);
    bandMans[1] = new BandManager("yellow", BAND2);
    bandMans[2] = new BandManager("blue", BAND3);
    // bandMans[3] = new BandManager("red2", BAND4);

    reset();
    movingFwd = false;
  }  // end of BandsAnalyzer()


  private void reset()
  // reset the band managers
  { for(int i=0; i < NUM_BANDS; i++)
      bandMans[i].clear();

    bandIdx = -1; blobIdx = -1;
  }  // end of reset()


  public void run()
  /* Use a JMFCapture object to take a picture every SNAP_INTERVAL ms, 
     analyze it, and then generate translation or rotation commands.
  */
  {
    camera = new JMFCapture(imSize);   // initialize the webcam
    System.out.println("**Camera Ready**");

    long duration;
    BufferedImage im = null;
    running = true;

    while (running) {
	  long startTime = System.currentTimeMillis();
      // System.out.println("Start loading image");
      im = camera.grabImage();  // take a snap
      analyzeImage(im);         // analyze the image
      applyBigBlob();           // convert blob info to translation/rotation cmds

      duration = System.currentTimeMillis() - startTime;

      if (im == null)
        System.out.println("Problem loading image");
      else {
        // System.out.println("Duration: " + duration + " ms");
        bandsPanel.showImage(im, duration);  // show the image in the JPanel
      }

      if (duration < SNAP_INTERVAL) {
        try {
          Thread.sleep(SNAP_INTERVAL-duration);  // wait until interval has passed
        } 
        catch (Exception ex) {}
      }
    }
    camera.close();    // close down the camera
  }  // end of run()


  // ----------------- image analysis ----------------------


  private void analyzeImage(BufferedImage im)
  /*
    The image is processed as a pixel array. Each pixel is
    compared to the predefined band colours, and if the pixel 
    colour is near to one of them then the pixel's coordinate is 
    added to a 'blob' for that band colour.

    When a blob grows large enough (madeBigBlob == true), the image 
    processing stops.
  */
  {
    if (im == null) {
      System.out.println("Input image is null");
      return;
    }

    reset();   // reset the bands analyzer

    // extract pixels from the image into an array
    int imWidth = im.getWidth();
    int imHeight = im.getHeight();
    int [] pixels = new int[imWidth * imHeight];
    im.getRGB(0, 0, imWidth, imHeight, pixels, 0, imWidth);

    int xc = 0;    // hold the current pixel coordinates
    int yc = 0;
    int bandId;   // id of band manager
    boolean madeBigBlob = false;

    // examine the pixels
    int i = 0;
    while((i < pixels.length) && (!madeBigBlob)) {
      bandId = isBandColour(pixels[i]);
      if (bandId != -1)   // pixel colour is a band colour
        madeBigBlob = addPointToBand(bandId, xc, yc);
      else      // pixel colour isn't a band colour
        pixels[i] = WHITE;   // clear the pixel to white

      // move to next coordinate in image
      xc++;
      if (xc == imWidth) {    // at end of row
        xc = 0;   // start next row
        yc++;
      }
      i++;
    }

    // update the image with the new pixels data
    im.setRGB(0, 0, imWidth, imHeight, pixels, 0, imWidth);
  }  // end of analyzeImage()



  private int isBandColour(int pixel)
  /* is the (r,g,b) pixel colour close to a band colour? 
     If it is then return the index of the band manager
     which is handling the band. */
  {
    // extract RGB components from the current pixel as integers
    int redVal = (pixel>>16)&255;
    int greenVal = (pixel>>8)&255;
    int blueVal = pixel&255;

    for(int i=0; i < NUM_BANDS; i++)
      if (bandMans[i].isBandColour(redVal, greenVal, blueVal))
        return i;
    return -1;
  }  // end of isBandColour()


  private boolean addPointToBand(int bandId, int x, int y)
  /* Add (x,y) to the band manager with bandId, and 
     report if a large blob has been made because of it. */
  {
    boolean madeBigBlob = false;

    if ((bandId < 0) || (bandId >= NUM_BANDS))
      System.out.println("Band ID out of range: " + bandId);
    else {
      int blobId = bandMans[bandId].addPoint(x,y);
      if (blobId != -1) {   // made a large-enough blob
        madeBigBlob = true;
        bandIdx = bandId;   // store indicies for large blob
        blobIdx = blobId;
      }
    }
    return madeBigBlob;
  }  // end of addPointToBand()


  // ----------------- use analysis info ----------------------

  private void applyBigBlob()
  /* Use the largest blob info to generate translation/rotation cmds.
     The blob's colour is used to define a possible rotation.
     The current blob's center point (pt) is compared to the
     previous image's blob center (prevCenterPt) to define a
     possible translation.
  */
  {
    if (bandIdx != -1) {  // there is a large blob
      BandManager bm = bandMans[bandIdx];
      Point pt = bm.getBlobCenter(blobIdx);   // blob's center pt
      // System.out.println( bm.getName() + " (" + pt.x + "," + pt.y + ")" );

      if (prevCenterPt != null) {   // there is a previous center point
        rotateView( bm.getName() );
        translateView(pt, prevCenterPt);
      }
      prevCenterPt = pt;  // save for next analysis
    }
    else
      System.out.println("No large blob");
  }  // end of applyBigBlob()


  private void rotateView(String bmName)
  // blob colour --> rotation
  {
    if (bmName.equals("red1") || bmName.equals("red2"))
      System.out.println("turn left");
    else if (bmName.equals("blue"))
      System.out.println("turn right");
  } // end of rotateView()


  private void translateView(Point currPt, Point prevPt)
  /* The change in the x values of the current center point
     (currPt) and the previous center point (prevPt) generates
     a translation forward.

     I don't use the y-coordinate change in this example.

     I'm assuming that a translation of the center to the left
     in the image means a movement 'forward'. However, some cameras 
     flip the webcam image so a translation 'forward' is a move to 
     the right in the image. This can be dealt with by switching the 
     true/false assignments in the if-test.
  */
  {
    int xChg = currPt.x - prevPt.x;

    if (xChg < -MIN_MOVE_DIST)
      movingFwd = true; 
    else if (xChg > (MIN_MOVE_DIST*2))    // stopping requires more of a change
      movingFwd = false; 

    if (movingFwd)
      System.out.println("  forwards");
  }  // end of translateView()


  // --------------------- finish -----------------------

  public void closeDown()
  /* closeDown() blocks until run() has called JMFCapture.close() 
     and finished. This avoids nasty OS effects after the application 
     has terminated, but it means that clicking on the close box
     'freezes' the application for 1-2 secs.
  */
  { 
    running = false;
    while (!camera.isClosed()) {
      try {
        Thread.sleep(SNAP_INTERVAL);
      } 
      catch (Exception ex) {}
    }
  } // end of closeDown()


}  // end of BandsAnalyzer class

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -