Avatar billede vindermartin Nybegynder
01. oktober 2003 - 21:05 Der er 5 kommentarer og
1 løsning

Webcam på egen side

Jeg regner med det er i Java det skal gøres, men så er jeg også tabt.

Jeg har lige købt et webcam og vil gerne sende det fra min egen side ud på nettet.. hvordan gør jeg?
Avatar billede _henrik Nybegynder
01. oktober 2003 - 22:11 #1
Her er et eksempel på hvordan du kan grabbe et Image fra dit webcam:

Du skal have installeret JMF 2.1.1 for at det virker

import java.io.*;
import java.awt.*;
import java.awt.image.*;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import javax.media.*;
import javax.media.control.*;
import javax.media.protocol.*;
import javax.media.util.*;
import javax.media.format.RGBFormat;
import javax.media.format.VideoFormat;

/**
*  Frame grabber class
**/
public class FrameGrabber extends Thread implements ControllerListener {
  /*  Default device name and format parameters to use if no properties file
  *  is provided
  */
    private final static String DEFAULT_DEV_NAME =
    "vfw:Microsoft WDM Image Capture (Win32):0";
    private final static String DEFAULT_X_RES = "160";
    private final static String DEFAULT_Y_RES = "120";
    private final static String DEFAULT_DEPTH = "24";

  private Properties videoProperties;

  /*  These objects are used for controlling access via wait and notify to
  *  ensure that the processor has been realised and the second thread has
  *  completed it's startup
  */
  private Object stateLock = new Object();
  private Object runLock = new Object();

  private Processor deviceProc = null;
  private PushBufferStream camStream;
  private PushBufferDataSource source = null;
  private BufferToImage converter;
  private Image currentImage;
  private boolean threadRunning = false;

  /**
  *  Constructor
  *
  *
  * @throws FrameGrabberException If we can't start up the camera
  **/
  public FrameGrabber() throws FrameGrabberException {
    /*  If the user chooses the no parameter form of the constructor we
    *  try to get the video property file name from the properties
    *  passed on the command line
    */
    String videoPropFile =
      System.getProperty("video.properties", "video.properties");

    setup(videoPropFile);
  }

  /**
  *  Constructor
  *
  * @param videoPropFile The name of the video properties file
  * @throws FrameGrabberException If we can't start up the camera
  **/
  public FrameGrabber(String videoPropFile) throws FrameGrabberException {
    setup(videoPropFile);
  }

  /**
  *  Setup method.  Configures webcam and JMF ready to get images
  *
  * @param videoPropFile The name of the video properties file
  * @throws FrameGrabberException If we can't start up the camera
  **/
  private void setup(String videoPropFile) throws FrameGrabberException {
    videoProperties = new Properties();

    if (videoPropFile != null) {
      try {
        FileInputStream fis = new FileInputStream(new File(videoPropFile));
        videoProperties.load(fis);
      } catch (IOException ioe) {
        System.out.println("Unable to access video properties");
        System.out.println(ioe.getMessage());
      }
    }

    Dimension viewSize = null;
    int viewDepth = 0;

    String cameraDevice =
      videoProperties.getProperty("device-name", DEFAULT_DEV_NAME);

    /*  Get the parameters for the video capture device from the properties
    *  file.  If not defined use default values
    */
    try {
      String pValue =
        videoProperties.getProperty("resolution-x", DEFAULT_X_RES);
      int xRes = Integer.parseInt(pValue);
      pValue = videoProperties.getProperty("resolution-y", DEFAULT_Y_RES);
      int yRes = Integer.parseInt(pValue);
      viewSize = new Dimension(xRes, yRes);
      pValue = videoProperties.getProperty("colour-depth", DEFAULT_DEPTH);
      viewDepth = Integer.parseInt(pValue);
    } catch (NumberFormatException nfe) {
      System.out.println("Bad numeric value in video properties file");
      System.exit(1);
    }

    /*  Try to get the CaptureDevice that matches the name supplied by the
    *  user
    */
    CaptureDeviceInfo device = CaptureDeviceManager.getDevice(cameraDevice);

    if (device == null)
      throw new FrameGrabberException("No device found [ " +
        cameraDevice + "]");

    RGBFormat userFormat = null;
    Format[] cfmt = device.getFormats();

    /*  Find the format that the user has requested (if available)  */
    for (int i = 0; i < cfmt.length; i++) {
      if (cfmt[i] instanceof RGBFormat) {
        userFormat = (RGBFormat)cfmt[i];
        Dimension d = userFormat.getSize();
        int bitsPerPixel = userFormat.getBitsPerPixel();
   
        if (viewSize.equals(d) && bitsPerPixel == viewDepth)
          break;

        userFormat = null;
      }
    }

    /*  Throw an exception if we can't find a format that matches the
    *  user's criteria
    */
    if (userFormat == null)
      throw new FrameGrabberException("Requested format not supported");

    /*  To use this device we need a MediaLocator  */
    MediaLocator loc = device.getLocator();

    if (loc == null)
      throw new FrameGrabberException("Unable to get MediaLocator for device");

    DataSource formattedSource = null;

    /*  Now create a dataSource for this device and set the format to
    *  the one chosen by the user.
    */
    try {
      formattedSource = Manager.createDataSource(loc);
    } catch (IOException ioe) {
      throw new FrameGrabberException("IO Error creating dataSource");
    } catch (NoDataSourceException ndse) {
      throw new FrameGrabberException("Unable to create dataSource");
    }

    /*  Setting the format is rather complicated.  Firstly we need to get
    *  the format controls from the dataSource we just created.  In order
    *  to do this we need a reference to an object implementing the
    *  CaptureDevice interface (which DataSource objects can).
    */
    if (!(formattedSource instanceof CaptureDevice))
      throw new FrameGrabberException("DataSource not a CaptureDevice");

    FormatControl[] fmtControls =
      ((CaptureDevice)formattedSource).getFormatControls();

    if (fmtControls == null || fmtControls.length == 0)
      throw new FrameGrabberException("No FormatControl available");

    Format setFormat = null;

    /*  Now we need to loop through the available FormatControls and try
    *  to set the format to the one we want.  According to the documentation
    *  even though this may appear to work, it may fail later on.  Since
    *  we know that the format is supported we hope that this won't happen
    */
    for (int i = 0; i < fmtControls.length; i++) {
      if (fmtControls[i] == null)
        continue;

      if ((setFormat = fmtControls[i].setFormat(userFormat)) != null)
        break;
    }

    /*  Throw an exception if we couldn't set the format  */
    if (setFormat == null)
      throw new FrameGrabberException("Failed to set camera format");

    /*  Connect to the DataSource  */
    try {
      formattedSource.connect();
    } catch (IOException ioe) {
      throw new FrameGrabberException("Unable to connect to DataSource");
    }

    /*  Since we don't want to display the output to the user at this stage
    *  we use a processor rather than a player to get frame access
    */
    try {
      deviceProc = Manager.createProcessor(formattedSource);
    } catch (IOException ioe) {
      throw new FrameGrabberException("Unable to get Processor for device: " +
        ioe.getMessage());
    } catch (NoProcessorException npe) {
      throw new FrameGrabberException("Unable to get Processor for device: " +
        npe.getMessage());
    }

    /*  In order to use the controller we have to put it in the realized
    *  state.  We do this by calling the realize method, but this will
    *  return immediately so we must register a listener (this class) to
    *  be notified when the controller is ready.
    */
    deviceProc.addControllerListener(this);
    deviceProc.realize();

    /*  Wait for the device to send an event telling us that it has
    *  reached the realized state
    */
    while (deviceProc.getState() != Controller.Realized) {
      synchronized (stateLock) {
        try {
          stateLock.wait();
        } catch (InterruptedException ie) {
          throw new FrameGrabberException("Failed to get to realized state");
        }
      }
    }

    deviceProc.start();

    /*  Get access to the PushBufferDataSource which will provide us with
    *  a means to get at the frame grabber
    */
    try {
      source = (PushBufferDataSource)deviceProc.getDataOutput();
    } catch (NotRealizedError nre) {
      /*  Should never happen  */
      throw new FrameGrabberException("Processor not realized");
    }
   
    /*  Now we can retrieve the PushBufferStreams that will enable us to
    *  access the data from the camera
    */
    PushBufferStream[] streams = source.getStreams();
    camStream = null;

    for (int i = 0; i < streams.length; i++) {
      /*  Use the first Stream that is RGBFormat (there should be only one  */
      if (streams[i].getFormat() instanceof RGBFormat) {
        camStream = streams[i];
        RGBFormat rgbf = (RGBFormat)streams[i].getFormat();
        converter = new BufferToImage(rgbf);
        break;
      }
    }

    System.out.println("Capture device ready");
  }

  /**
  *  Get an image from the camera as an AWT Image object
  *
  * @returns The current image from the camera
  **/
  public Image getImage() {
    /*  Since we are using a second thread to grab the images from the webcam
    *  we need to ensure that an image has been aquired.
    *  We do this by using a flag which will be set to true in the run()
    *  method.  If this is false we wait until the run method notifies us
    *  that there is an image to collect
    */
    while (threadRunning == false) {
      synchronized (runLock) {
        try {
          runLock.wait();
        } catch (InterruptedException ie) {
          // Ignore
        }
      }
    }

    return accessInternalImage(null);
  }

  /**
  *  Get an image from the camera as a BufferedImage
  *
  * @returns The current image from the camera
  **/
  public BufferedImage getBufferedImage() {
    return (BufferedImage)getImage();
  }

  /**
  *  Run method for Thread class
  **/
  public void run() {
    System.out.println("Capture thread starting...");
    Buffer b = new Buffer();

    /*  Simply loop forever grabbing images from the web cam and storing
    *  them so that the user can retrieve them when required.
    */
    while (true) {
      try {
        camStream.read(b);
      } catch (Exception e) {
        //  Ignore.  Nothing we can really do about this
      }

      Image i = converter.createImage(b);
      accessInternalImage(i);

      /*  If this is the first image we've collected we need to advertise
      *  to the main thread that there is an image ready and then notify
      *  the main thread in case it is waiting on the image
      */
      if (!threadRunning) {
        threadRunning = true;

        synchronized (runLock) {
          runLock.notifyAll();
        }
      }
    }
  }

  /**
  *  Method called when a controller event is received (implements
  *  ControllerListener interface)
  *
  * @param ce The controller event
  **/
  public void controllerUpdate(ControllerEvent ce) {
    if (ce instanceof RealizeCompleteEvent) {
      synchronized (stateLock) {
        stateLock.notifyAll();
      }
    }
  }

  /**
  *  Method that controls access to the global image variable.  This ensures
  *  that there is no confusion over one thread reading an image whilst
  *  another is writing to it
  *
  * @param image The image to store (null indicates retrieval of the image)
  * @return The image (if the parameter was null)
  **/
  private synchronized Image accessInternalImage(Image image) {
    if (image == null) {
      return currentImage;
    }

    currentImage = image;
    return null;
  }
}

---------------

public class FrameGrabberException extends Exception {
  public FrameGrabberException(String msg) {
    super(msg);
  }
}
Avatar billede vindermartin Nybegynder
01. oktober 2003 - 22:26 #2
hvad er det der JMF????
Avatar billede _henrik Nybegynder
01. oktober 2003 - 22:34 #3
Java Media Framework (JMF) er et API til java

Det kan hentes her:
http://java.sun.com/products/java-media/jmf/2.1.1/download.html
Avatar billede _henrik Nybegynder
03. oktober 2003 - 14:09 #4
Kan du få det til at virke ?
Avatar billede vindermartin Nybegynder
03. oktober 2003 - 16:17 #5
bortset fra jeg er ringe til at sætte det ind i et tag eller hvad det hedder så går det fint :-)
Avatar billede _henrik Nybegynder
08. oktober 2003 - 21:39 #6
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester