Saturday, October 26, 2013

Java OpenCV Webcam

Camera is a very important piece of equipment in computer vision. My first tutorial will be a webcam program based on OpenCV. 1. We need an efficient piece of code that convert OpenCV image, a Mat, to a BufferedImage.
import java.awt.image.BufferedImage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

public class Mat2Image {
    Mat mat = new Mat();
    BufferedImage img;
    byte[] dat;
    public Mat2Image() {
    }
    public Mat2Image(Mat mat) {
        getSpace(mat);
    }
    public void getSpace(Mat mat) {
        this.mat = mat;
        int w = mat.cols(), h = mat.rows();
        if (dat == null || dat.length != w * h * 3)
            dat = new byte[w * h * 3];
        if (img == null || img.getWidth() != w || img.getHeight() != h
            || img.getType() != BufferedImage.TYPE_3BYTE_BGR)
                img = new BufferedImage(w, h, 
                            BufferedImage.TYPE_3BYTE_BGR);
        }
        BufferedImage getImage(Mat mat){
            getSpace(mat);
            mat.get(0, 0, dat);
            img.getRaster().setDataElements(0, 0, 
                               mat.cols(), mat.rows(), dat);
        return img;
    }
    static{
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }
}
2. Here is a simple class that captures video:
import java.awt.image.BufferedImage;
import org.opencv.core.Core;
import org.opencv.highgui.VideoCapture;

public class VideoCap {
    static{
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    VideoCapture cap;
    Mat2Image mat2Img = new Mat2Image();

    VideoCap(){
        cap = new VideoCapture();
        cap.open(0);
    } 
 
    BufferedImage getOneFrame() {
        cap.read(mat2Img.mat);
        return mat2Img.getImage(mat2Img.mat);
    }
}
3. Now we need a JFrame to display the video:
package org.ski;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class MyFrame extends JFrame {
    private JPanel contentPane;

  /**
  * Launch the application.
  */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MyFrame frame = new MyFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

  /**
  * Create the frame.
  */
    public MyFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 650, 490);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
  
        new MyThread().start();
    }
 
    VideoCap videoCap = new VideoCap();
 
    public void paint(Graphics g){
        g = contentPane.getGraphics();
        g.drawImage(videoCap.getOneFrame(), 0, 0, this);
    }
 
    class MyThread extends Thread{
        @Override
        public void run() {
            for (;;){
                repaint();
                try { Thread.sleep(30);
                } catch (InterruptedException e) {    }
            }  
        } 
    }
}

32 comments:

  1. Works perfect, first trial! Wow! bravo and merci!

    ReplyDelete
  2. Hey,
    the problem is that highgui is not supported anymore under java.
    Do you have any suggestions?
    Thanks

    ReplyDelete
  3. When I run this code "as is" I am getting red and blue channels swapped.

    ReplyDelete
    Replies
    1. You can use this to swap red and blue channels:

      Imgproc.cvtColor(mat,mat,Imgproc.COLOR_RGB2BGR);

      Delete
    2. This code is very helpful, but where should this line go to swap red and blue back?

      Delete
    3. You need to place it in the getSpace() method in your Mat2Image class.

      Delete
  4. Perfect. the best tutorial -code on internet.

    Many thanks

    ReplyDelete
  5. your code is really help me sir. i wanna ask you how many frames per second that we got from this code.
    i've tried to analyzed it for this code which means for create an image file:
    public void paint(Graphics g){
    g = contentPane.getGraphics();
    g.drawImage(videoCap.getOneFrame(), 0, 0, this);
    }
    and it takes 3FPS. i used webcam camera with resolution 640x480 it should take 7FPS. but i got 3 FPS. can you help me ?

    thanks

    ReplyDelete
  6. It's so perfect! Thank you so much!! XD

    ReplyDelete
  7. I'm sorry, I'm new at this, aren't we supposed to have a main to run the code?

    please help

    ReplyDelete
  8. Hi,

    Is it possible to use three cameras with this code? I tried with three cameras, it works if they are displayed in different windows but it does not work to be displayed in the same Jframe.
    Do you know if is it possible to have 3 videos streamed in the same window in different JPnalels?

    Thanks in advance.

    ReplyDelete
  9. Спасибо за код и комментарии! мне тоже помогло смещение каналов синего и красного. Теперь мне интересно как добавить распознавание лиц и автомобильных номеров к этому примеру.

    ReplyDelete
  10. Thanks, this is a very useful introduction to OpenCV Java.

    I hope that you can find time to write some more blogs.

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. can i detect color in live stream and how?

    ReplyDelete
  13. How many classes should I create in netbeans to run this?

    ReplyDelete
  14. sir, I need java code for Capturing image and save it as file. I am waiting for your reply sir. thank you

    ReplyDelete
  15. This comment has been removed by the author.

    ReplyDelete
  16. how can i change Jframe to a Jpanel?

    ReplyDelete
  17. to get output directly relating to your camera. Now you can control your camera with the Gphoto2 command line tool but first see if your camera it is recognized by the command 8mp Hikvision

    ReplyDelete
  18. Replace:

    VideoCap(){
    cap = new VideoCapture();
    cap.open(0);
    }

    with:

    VideoCap(){

    cap = new VideoCapture("http://admin:admin@192.168.1.8/cgi/mjpg/mjpeg.cgi");

    }

    If you want to read from an ip camera, replace with a url.
    To find out your specific manufacturer url google for it.
    I use Trendnet: https://www.ispyconnect.com/man.aspx?n=Trend+Net#

    ReplyDelete
  19. Thank you for sharing your code. It is a nice stepup into Opencv and Java.

    ReplyDelete
  20. Thank you very much sir. You're a genious...!!!

    ReplyDelete
  21. The author has composed this blog in an extremely informal way.
    use-droidcam-wireless-webcam

    ReplyDelete
  22. sir i want to save the captured video in local storage space.

    ReplyDelete