使用opencv java打开视频文件

使用opencv java打开视频文件,java,file,opencv,video,Java,File,Opencv,Video,所以有了OpenCV! 有人能告诉我如何用它打开视频文件吗 我试着在网上到处找,但什么也没找到。VideoCapture类的文档不是很有用,因为它给出了一个C#示例,并展示了如何从网络摄像头进行捕获 也没有帮助,因为没有(public)方法可以为其提供文件名字符串 但是它应该像API中写的那样工作。但事实并非如此 然而,VideoCapture类中有一个private方法,带有一个sting参数 请回答是否有解决方案,或者即使您有相同的问题。 加里耶 更新:(2017年5月) 自版本3.0.0以

所以有了OpenCV! 有人能告诉我如何用它打开视频文件吗

我试着在网上到处找,但什么也没找到。VideoCapture类的文档不是很有用,因为它给出了一个C#示例,并展示了如何从网络摄像头进行捕获

也没有帮助,因为没有(public)方法可以为其提供文件名字符串

但是它应该像API中写的那样工作。但事实并非如此 然而,VideoCapture类中有一个private方法,带有一个sting参数

请回答是否有解决方案,或者即使您有相同的问题。 加里耶

更新:(2017年5月)


自版本3.0.0以来,VideoCapture类有一个构造函数,它接受字符串参数。所以现在这个问题有一个简单的解决方案

对我来说,这是一个谜,为什么所谓的opencv自动生成java包装器缺少这一功能。我首先使用VideoCapture(字符串文件名)构造函数创建了一个新的VideoCapture类,并将其称为私有本机方法。这会导致不满意的链接错误:

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)
我们在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;
}
关键而棘手的一步是添加jni导出。尤其是为JNICALL找到正确的方法名被证明是一项挑战,因为构造函数是重载的,并且以java类作为参数。此外,我们需要将JavaSting转换为c字符串。其余的是从其他构造函数复制的

在opencv-2.4.6/modules/java/generator/src/cpp/VideoCapture.cpp中,我们添加了这个新的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;
    }
}
重新编译OpenCV,它应该可以工作。

以下是一个示例:

    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();

        }
    }
}`

如果您使用的是Windows,请将C:\opencv\build\x86\vc11\bin添加到Path变量中

以下是我的工作方式

VideoCapture=newvideocapture();
捕获。打开(“Vid.mp4”);
垫架=新垫();
对于(;;){
capture.read(frame);//将捕获的帧读取到Mat图像中
imshow(“显示”,框架);
如果(cvWaitKey(30)>=0)中断;

}
如果您使用的是新版本的Java,我就是这样让它工作的

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;
    }

}

可下载版本为2.4.7.1,但当您下载源代码并编译(3.00版)时,此问题已得到修复。如中所示,有一个带字符串参数的VideoCapture构造函数。此解决方案在版本3.00及之后不再必要,也不再可能(因为所有路径都已更改)。我找不到文件…命名约定JNIEXPORT jlong JNICALL Java_org\u opencv\u highgui\u VideoCapture\u n\u 1VideoCapture\u Ljava_lang\u String\u 2(JNIEnv*env,jclass,jstring filename);不适用于我,仍然获得java.lang.unsatifiedLinkError:未找到本机方法:org.opencv.highgui.VideoCapture.n\u VideoCapture:(Ljava/lang/String;)JI抱歉,但这绝不是答案。看看当前的情况,没有接受字符串的构造函数。这就是问题所在!事实上,在回答之前,你必须先阅读问题!试着解释你的代码,而不是仅仅给出它。另外,确保您添加了其他答案没有提供的内容,否则答案是pointless@AbdulMuheet很抱歉,我不再具有验证您的问题的设置。
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;
    }