Tuesday, April 3, 2012

WebCam Video Capture in Java

I got a lot of requests asking for how to do video capturing in Java as comments on my previous post :

Capture photo / image from Web Cam / USB Camera using Java

In this quick post i will highlight how i did this functionality in Interactive4j

We will use the library LTI-CIVIL which is part of FMJ (Freedom for Media in Java).



PreRequisities:

-Download the library and place it correctly in your classpath and load the native library using JVM parameter exactly as the previous mentioned post above.
Download from here:  https://sourceforge.net/projects/lti-civil/

Steps:

1) Create Interface For Captured Images:
public interface CaptureListener {
/**
* Method called once capturing of the web cam jpg file is done.
* @param filename
*/
public void setCaptureFile(File filename);
}

2) Create A Wrapper Class:
This class wrap the camera functionality..

/**
* JHCaptureUtil class
* Used for capture images through the usb (camera, scanner,...etc)
* Osama Oransa
* Interactive4J
* (c) 2011
**/
package osa.ora.utils;

import com.lti.civil.*;
import com.lti.civil.awt.AWTImageConverter;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import osa.ora.utils.faces.CaptureListener;

/**
*
* @author mabdelmo
*/
public class JHCaptureUtil implements CaptureObserver {

CaptureStream captureStream = null;
CaptureListener captureListener;
String fileName;
/**
* Constructor accept the listener and file to save image into.
* @param captureListener
* @param fileName
*/
public JHCaptureUtil(CaptureListener captureListener, String fileName) {
this.fileName = fileName;
this.captureListener = captureListener;
init();
}
private void init(){
System.out.println("Init....");
/*
* initialize capturing to use the current devices...
*/
CaptureSystemFactory factory = DefaultCaptureSystemFactorySingleton.instance();
CaptureSystem system;
try {
system = factory.createCaptureSystem();
system.init();
List list = system.getCaptureDeviceInfoList();
int i = 0;
if (i < list.size()) {
CaptureDeviceInfo info = (CaptureDeviceInfo) list.get(i);
System.out.println((new StringBuilder()).append("Device ID ").append(i).append(": ").append(info.getDeviceID()).toString());
System.out.println((new StringBuilder()).append("Description ").append(i).append(": ").append(info.getDescription()).toString());
captureStream = system.openCaptureDeviceStream(info.getDeviceID());
captureStream.setObserver(this);
}
} catch (CaptureException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Start capture method
*/
public void start() {
//System.out.println("Start....");
try {
captureStream.start();
} catch (CaptureException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Stop capture method
*/
public void stop() {
//System.out.println("Stop....");
try {
captureStream.stop();
} catch (CaptureException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
*
* @param stream
* @param image
*/
public void onNewImage(CaptureStream stream, Image image) {
//System.out.println("get new image....");
byte bytes[] = null;
try {
if (image == null) {
return;
}
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(os);
jpeg.encode(AWTImageConverter.toBufferedImage(image));
os.close();
bytes = os.toByteArray();
if (bytes == null) {
return;
}
} catch (Throwable t) {
t.printStackTrace();
bytes = null;
return;
}
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
File currentImageFile = new File(fileName);
FileOutputStream fos = new FileOutputStream(currentImageFile);
fos.write(bytes);
fos.close();
captureListener.setCaptureFile(currentImageFile);
} catch (IOException ex) {
Logger.getLogger(JHCaptureUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
*
* @param stream
* @param ce
*/
public void onError(CaptureStream stream, CaptureException ce) {
System.out.println("Error : "+ce.getStackTrace());
}
}




3) Write the code that control your wrapper class:
Here is sample usage code that display a dialog with one image or a video .. You need to add 2 buttons 1 for image capture and 1 for video capture and add the action listeners on these buttons..


int mode=0;
static int ONE_PHOTO=0;
static int MULTI_PHOTO=1;
JHCaptureUtil webCam;

//this method to capture one image

private void captureImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
mode=ONE_PHOTO;
if(webCam==null) webCam=new JHCaptureUtil(this, "/myWebCamPic.jpg");
webCam.start();
}

private void captureVideoActionPerformed(java.awt.event.ActionEvent evt) {
mode=MULTI_PHOTO;
if(webCam==null) webCam=new JHCaptureUtil(this, "/myWebCamPic.jpg");
webCam.start();
}


You class must implements : CaptureListener , this interface has 1 method inside it :
public void setCaptureFile(File filename);

And this is the interface method implementation that display the image without saving the photos (you can change the implementation)


JDialog monitorjDialog;
JLabel monitorLabel;
JScrollPane monitorScroll;

public void setCaptureFile(File filename) {
if(mode==ONE_PHOTO){
System.out.println("No more photos");
JDialog jDialog=new JDialog(this.getFrame(),true);
Image image=ImageUtils.loadJPG(filename.getAbsolutePath());
jDialog.setBounds(this.getFrame().getX()+50,this.getFrame().getY()+50,500, 500);
JLabel label=new JLabel(new ImageIcon(image));
JScrollPane jscroll=new JScrollPane(label);
jDialog.add(jscroll);
jDialog.setVisible(true);
jDialog.validate();
webCam.stop();
}else{
System.out.println("display new photo");
if(monitorjDialog==null) {
monitorjDialog=new JDialog(this.getFrame(),false);
monitorjDialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
webCam.stop();
}
});
Image image=ImageUtils.loadJPG(filename.getAbsolutePath());
monitorjDialog.setBounds(this.getFrame().getX()+50,this.getFrame().getY()+50,image.getWidth(null), image.getHeight(null));
monitorLabel=new JLabel(new ImageIcon(image));
monitorScroll=new JScrollPane(monitorLabel);
monitorjDialog.add(monitorScroll);
monitorjDialog.setVisible(true);
monitorjDialog.validate();
}else{
Image image=ImageUtils.loadJPG(filename.getAbsolutePath());
monitorjDialog.remove(monitorScroll);
monitorScroll.remove(monitorLabel);
monitorLabel=new JLabel(new ImageIcon(image));
monitorScroll=new JScrollPane(monitorLabel);
monitorjDialog.add(monitorScroll);
monitorjDialog.validate();
}
}
}

4) Utility method used: ImageUtils.loadJPG ..
public static Image loadJPG(String filename) {
FileInputStream in = null;
try {
in = new FileInputStream(filename);
} catch (java.io.FileNotFoundException io) {
System.out.println("File Not Found");
}
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
BufferedImage bi = null;
try {
bi = decoder.decodeAsBufferedImage();
in.close();
} catch (java.io.IOException io) {
System.out.println("IOException");
}
return bi;
}

That's all needed !

44 comments:

  1. Nice post.... thank you

    ReplyDelete
    Replies
    1. hi,

      how write jsp program to connect pc to web cam and perform all operations like capuring images,web chat,video recording etc

      Delete
    2. Please refer to the other post : http://osama-oransa.blogspot.co.uk/2012/06/accessing-webcam-within-jsp.html

      Delete
    3. thanku ,but it is only for capturing images

      Delete
    4. video is a series of images :-)

      Delete
  2. hai,

    I'm a beginner. can u please help me to deploy this project. I got confused in creating classes. If you give me the class details (which part of the code should written in which class) I will be more helpful.

    Thanks in advance

    ReplyDelete
    Replies
    1. this is very difficult .u need to learn java well before start in advanced topics.

      Delete
  3. hi kindly help me in making video conferencing . i am in problem

    ReplyDelete
  4. Hi i am using x64-win. any other dll or something else to make it run?
    Thx in advance.

    ReplyDelete
    Replies
    1. I don't develop this lib, i just use it , you may contact them for win-64 support.

      Delete
  5. btw how to display the image (image stream) if i use mode "MULTI-PHOTO" on JPanel?

    ReplyDelete
    Replies
    1. please go check the code in interactive4j open source project , Search in my blog to find it.. it has a demo for image and video...

      Delete
  6. سلام عليكم اخي اسامة, تحية طيبة .. لدية سؤال هل أستطيع تشغيل أكثر من كامرة في ال فريم باستخدام اثنان من البنلات , ارجوك وا1ا لديك فكرة ساعدني بها ...وشكرا

    ReplyDelete
  7. سلام عليكم اخي اسامة,لدية سؤال هل لي ان استخدم اكثر من كامرة في نفس الوقت باستخدام two Panels وهل ليك فكرة تساعدني بها وشكرا

    ReplyDelete
  8. I don't think by using this way would be possible because it used the embeded camera which is only one, you may search for another way.

    ReplyDelete
  9. i just want to know the name of the lib that i have to use..
    thanx in advance

    ReplyDelete
    Replies
    1. The library LTI-CIVIL which is part of FMJ (Freedom for Media in Java).

      Delete
  10. i want to implement this without flash
    is this possible?

    ReplyDelete
  11. Sir, I have a question may be n't related to this topic.
    How can I implement the live tv channel streaming in website.
    please tell me the procedure how can i dot that.

    ReplyDelete
  12. Sir, FMG is good I will understand it tomorrow but a question in my mind, could you please tell me that,
    why we not use JMF lib for media streaming because this lib is developed by more popular organizations like SUN,IBM,Intel etc. I think JMF would be better then other. I tried to stream video with the help of JMF but I have not success. tell me these benefits and drawback.

    ReplyDelete
    Replies
    1. You can try, but it is not developed since long time and it might not working on recent operating systems as well.

      Delete
  13. Hi,

    Very informative post. I would like to ask you whether it is possible to use LTI-CIVIL on windows 64 bit. If so, from where can i download the jar files specific to 64 bit. Please help.

    ReplyDelete
    Replies
    1. don't know if they provide a build for that or not, but i can assume you can build the lib on 64 bit.

      Delete
  14. hey how can i capture image from a video using java?? Can u help me out please

    ReplyDelete
    Replies
    1. Save the image you want in the method: onNewImage

      Delete
    2. actually i want to capture image from a specified video. not from web cam.

      Delete
    3. You need to open the video using its decoder and get the frame that you need and save it into image file.

      Delete
    4. how to perform that using java??? can u guide me i am a newbee to that..

      Delete
    5. It is not a big deal, the code looks like:
      int frameNumber = 150;
      BufferedImage frame = FrameGrab.getFrame(new File("filename.mp4"), frameNumber);
      ImageIO.write(frame, "png", new File("frame_150.png"));

      Where the frame number is the frame you want to save as picture, each video has frame rate/second, you need to multiply the frame rate x seconds to know which frame you want to save as image.


      You can get the library and samples from the following URL:
      http://jcodec.org/

      Delete
  15. Can you tell me which all classes to create and how to run this program? I'm using netbeans.


    Thanks in advance

    ReplyDelete
    Replies
    1. Download the open source project Interactive4J to get the library and sample code of how to use this.

      Delete
  16. Thanks for quick reply , I'm having problems running the jar file,some path problem I have encountered.....can you please mail me the entire project file from your computer?

    Thanks.

    ReplyDelete
    Replies
    1. I have all the files from the link, how to proceed further?

      Delete
    2. yea which link do you refer to ?

      Delete
    3. http://sourceforge.net/projects/interactive4j/

      Delete
    4. Download the source code zip file, open it as a project in netbeans after unzip it.
      Download the lib folder into some location and use it by adding the following to JVM run parameters:
      -Djava.library.path="\......path......\lti-civil-20070920-1721\native\win32-x86"
      This represents the path to the library that you have downloaded but for a specific folder according to your model.
      You can also download the jar file and execute it with the same JVM parameter.

      Delete
    5. Duly noted, there are three Interactive4j zip files, one reading demo v1.0,jmf v1.0 and the other v1.0. I'm getting confused as to which one to unzip..

      Please let me know as soon as possible.

      Delete
    6. Interactive4J is a utility, so you need to download it together with the demo app so you can understand how to use it : Interactive4JDemo-v1.0.zip
      You need also to download the library and put it in the run using -D

      Delete
    7. I am getting the following errors after I've followed what you have told..



      C:\Users\Standby Laptop - 25\Documents\NetBeansProjects\Interactive4J\src\osa\ora\utils\ImageUtils.java:21: error: package com.sun.image.codec.jpeg does not exist
      import com.sun.image.codec.jpeg.*;
      C:\Users\Standby Laptop - 25\Documents\NetBeansProjects\Interactive4J\src\osa\ora\utils\JHCaptureUtil.java:10: error: package com.lti.civil does not exist
      import com.lti.civil.*;
      C:\Users\Standby Laptop - 25\Documents\NetBeansProjects\Interactive4J\src\osa\ora\utils\JHCaptureUtil.java:11: error: package com.lti.civil.awt does not exist
      import com.lti.civil.awt.AWTImageConverter;
      C:\Users\Standby Laptop - 25\Documents\NetBeansProjects\Interactive4J\src\osa\ora\utils\JHCaptureUtil.java:12: error: package com.sun.image.codec.jpeg does not exist
      import com.sun.image.codec.jpeg.JPEGCodec;
      C:\Users\Standby Laptop - 25\Documents\NetBeansProjects\Interactive4J\src\osa\ora\utils\JHCaptureUtil.java:13: error: package com.sun.image.codec.jpeg does not exist
      import com.sun.image.codec.jpeg.JPEGImageEncoder;
      C:\Users\Standby Laptop - 25\Documents\NetBeansProjects\Interactive4J\src\osa\ora\utils\JHCaptureUtil.java:28: error: cannot find symbol
      public class JHCaptureUtil implements CaptureObserver {
      symbol: class CaptureObserver

      Delete
    8. You are missing dependency for the project plus the 1st error seems the class is not longer available, Google it and you'll find the replacement.

      Delete
  17. This comment has been removed by the author.

    ReplyDelete