Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

open video file with opencv java

so there is OpenCV for Java now...! Can anyone tell me how to open Videofiles with it ?

I tryed and look all over the internet, but found nothing. The documentation of the VideoCapture class is not very helpfull, becaus it gives a C# example and show how to capture from a webcam.

the Q&A of OpenCV doesnt help either, because there is no (public) method to whom you can give a filename string.

BUT it should work as written in the API. But it doesn't There is however a privte method in the VideoCapture class with a sting parameter.

please answer if have a solution, or even if you have the same problem. garyee

UPDATE: (May 2017)

since Version 3.0.0 There is a constructor for the VideoCapture class that takes a string argument. So there is a easy solution to this Problem now!

like image 945
Flummiboy Avatar asked Jul 01 '13 10:07

Flummiboy


3 Answers

To me its a mystery why the so called automatically generated java wrapper for opencv is lacking this functionality. I first created a new VideoCapture class with a VideoCapture(String filename) constructor and called the private native method. This lead to an an unsatisfied link error:

Exception in thread "main" java.lang.UnsatisfiedLinkError:       org.opencv.highgui.VideoCapture.n_VideoCapture(Ljava/lang/String;)J
    at org.opencv.highgui.VideoCapture.n_VideoCapture(Native Method)
    at org.opencv.highgui.VideoCapture.<init>(VideoCapture.java:90)
    at Tester.main(Tester.java:30)

This indicates that the corresponding JNIEXPORT is missing. Luckily this can be fixed.

Surprisingly the needed c-constructor is already defined in opencv-2.4.6/modules/highgui/include/opencv2/highgui/highgui.cpp

CV_WRAP VideoCapture(const string& filename);

We add the constructor we long to the VideoCapture class in opencv-2.4.6/modules/java/generator/src/java/highgui+VideoCapture.java:

//
// C++: VideoCapture::VideoCapture(const string& filename)
//

// javadoc: VideoCapture::VideoCapture(String filename)
public VideoCapture(String filename)
{
    nativeObj = n_VideoCapture(filename);

    return;
}

The crucial and tricky step was to add the jni export. Especially finding the right method name for the JNICALL proved to be challenging, since the constructor is overloaded and takes a java class as argument. Additionally we need to convert the java sting into a c-string. The rest is copied from the other constructors.

In opencv-2.4.6/modules/java/generator/src/cpp/VideoCapture.cpp we add this new JNIEXPORT:

//
//   VideoCapture::VideoCapture(const string& filename)
//

JNIEXPORT jlong JNICALL Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__Ljava_lang_String_2
(JNIEnv* env, jclass, jstring filename);

JNIEXPORT jlong JNICALL Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__Ljava_lang_String_2
(JNIEnv* env, jclass, jstring filename)
{
    try {
        LOGD("highgui::VideoCapture_n_1VideoCapture__Ljava_lang_String_2()");
        const char* jnamestr = env->GetStringUTFChars(filename, NULL);
        string stdFileName(jnamestr);
        VideoCapture* _retval_ = new VideoCapture( jnamestr );

        return (jlong) _retval_;
    } catch(cv::Exception e) {
        LOGD("highgui::VideoCapture_n_1VideoCapture__Ljava_lang_String_2() catched cv::Exception: %s", e.what());
        jclass je = env->FindClass("org/opencv/core/CvException");
        if(!je) je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        return 0;
    } catch (...) {
        LOGD("highgui::VideoCapture_n_1VideoCapture__Ljava_lang_String_2() catched unknown exception (...)");
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {highgui::VideoCapture_n_1VideoCapture__Ljava_lang_String_2()}");
        return 0;
    }
}

Recompile OpenCV and it should work.

like image 106
mirel7c3 Avatar answered Oct 16 '22 19:10

mirel7c3


here is an example :

    public static void main(String[] args) {
    Mat frame = new Mat();
    VideoCapture camera = new VideoCapture("C:/Users/SAAD/Desktop/motion.mp4");
    JFrame jframe = new JFrame("Title");
    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JLabel vidpanel = new JLabel();
    jframe.setContentPane(vidpanel);
    jframe.setVisible(true);

    while (true) {
        if (camera.read(frame)) {

            ImageIcon image = new ImageIcon(Mat2bufferedImage(frame));
            vidpanel.setIcon(image);
            vidpanel.repaint();

        }
    }
}`

if you are using Windows add C:\opencv\build\x86\vc11\bin to the Path variable

like image 41
WALI Avatar answered Oct 16 '22 18:10

WALI


If you are using the new version of Java, this is how I got it to work.

import org.opencv.core.*;
import org.opencv.videoio.*;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;

import javax.swing.*;public class MainStruct {

public class MainStruct {

static { 
    try {
    System.load("C:opencv\\build\\x64\\vc14\\bin\\opencv_ffmpeg320_64.dll");
    } catch (UnsatisfiedLinkError e) {
        System.err.println("Native code library failed to load.\n" + e);
        System.exit(1);
    }
}

public static void main(String[] args)
{
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    //Create new MAT object
    Mat frame = new Mat();

    //Create new VideoCapture object
    VideoCapture camera = new VideoCapture("C:\\**VideoFileLocation**");

    //Create new JFrame object
    JFrame jframe = new JFrame("Video Title);

    //Inform jframe what to do in the event that you close the program
    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create a new JLabel object vidpanel
    JLabel vidPanel = new JLabel();

    //assign vidPanel to jframe
    jframe.setContentPane(vidPanel);

    //set frame size
    jframe.setSize(2000, 4000);

    //make jframe visible
    jframe.setVisible(true);

    while (true) {
        //If next video frame is available
        if (camera.read(frame)) {
            //Create new image icon object and convert Mat to Buffered Image
            ImageIcon image = new ImageIcon(Mat2BufferedImage(frame));
            //Update the image in the vidPanel
            vidPanel.setIcon(image);
            //Update the vidPanel in the JFrame
            vidPanel.repaint();

        }
    }
}

public static BufferedImage Mat2BufferedImage(Mat m) {
    //Method converts a Mat to a Buffered Image
    int type = BufferedImage.TYPE_BYTE_GRAY;
     if ( m.channels() > 1 ) {
         type = BufferedImage.TYPE_3BYTE_BGR;
     }
     int bufferSize = m.channels()*m.cols()*m.rows();
     byte [] b = new byte[bufferSize];
     m.get(0,0,b); // get all the pixels
     BufferedImage image = new BufferedImage(m.cols(),m.rows(), type);
     final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
     System.arraycopy(b, 0, targetPixels, 0, b.length);  
     return image;
    }

}

like image 3
TheoreticallyNick Avatar answered Oct 16 '22 18:10

TheoreticallyNick