【问题标题】:open video file with opencv java用opencv java打开视频文件
【发布时间】:2013-06-28 10:04:13
【问题描述】:

所以Java now... 有 OpenCV! 谁能告诉我如何用它打开视频文件?

我尝试在整个互联网上寻找,但一无所获。 VideoCapture 类的文档不是很有帮助,因为它提供了一个 C# 示例并展示了如何从网络摄像头捕获。

Q&A of OpenCV 也无济于事,因为没有(公共)方法可以向其提供文件名字符串。

但它应该按照 API 中的说明工作。但它没有 然而,VideoCapture 类中有一个带有 sting 参数的私有方法。

如果有解决方案,或者即使您有同样的问题,请回答。 加里耶

更新:(2017 年 5 月)

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

【问题讨论】:

    标签: java file opencv video


    【解决方案1】:

    这就是它对我的工作方式。

    VideoCapture capture=new VideoCapture();
    capture.open("Vid.mp4");
    Mat frame=new Mat();
                
       
    for(;;){
       capture.read(frame); //reads captured frame into the Mat image
       imshow("Display",frame);
       if(cvWaitKey(30) >= 0) break;
    }

    【讨论】:

    • @AbdulMuheet 抱歉,我不再有验证您的问题的设置。
    【解决方案2】:

    如果您使用的是新版本的 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;
        }
    

    }

    【讨论】:

    • 试着解释你的代码,而不是仅仅给出它。另外,请确保您添加了其他答案未提供的内容,否则答案毫无意义
    【解决方案3】:

    这是一个例子:

        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 变量中

    【讨论】:

    • 很抱歉,但这绝不是答案。看看当前的api 没有构造函数接受一个字符串。这是什么问题!你实际上必须在回答之前阅读问题!
    【解决方案4】:

    对我来说,为什么所谓的 opencv 自动生成的 java 包装器缺少此功能是个谜。我首先使用 VideoCapture(String filename) 构造函数创建了一个新的 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)
    

    这表示缺少相应的 JNIEXPORT。 幸运的是,这可以修复。

    令人惊讶的是,所需的 c 构造函数已经在 opencv-2.4.6/modules/highgui/include/opencv2/highgui/highgui.cpp

    中定义了
    CV_WRAP VideoCapture(const string& filename);
    

    我们在opencv-2.4.6/modules/java/generator/src/java/highgui+VideoCapture.java中的VideoCapture类中添加我们所长的构造函数:

    //
    // C++: VideoCapture::VideoCapture(const string& filename)
    //
    
    // javadoc: VideoCapture::VideoCapture(String filename)
    public VideoCapture(String filename)
    {
        nativeObj = n_VideoCapture(filename);
    
        return;
    }
    

    关键而棘手的一步是添加 jni 导出。尤其是为 JNICALL 找到正确的方法名称被证明是具有挑战性的,因为构造函数被重载并且需要一个 java 类作为参数。此外,我们需要将 java 字符串转换为 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,它应该可以工作了。

    【讨论】:

    • 可下载的版本是 2.4.7.1 但是当您下载源代码并编译(版本 3.00)时,此问题已得到修复。因为有一个带有字符串参数的 VideoCapture 构造函数。
    • 此解决方案不是必需的,并且在 3.00 版及之后不再可行(因为所有路径都已更改)。我找不到文件...
    • 命名约定 JNIEXPORT jlong​​ JNICALL Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__Ljava_lang_String_2 (JNIEnv* env, jclass, jstring 文件名);对我不起作用,仍然出现 java.lang.UnsatisfiedLinkError: Native method not found: org.opencv.highgui.VideoCapture.n_VideoCapture:(Ljava/lang/String;)J
    猜你喜欢
    • 2019-11-22
    • 1970-01-01
    • 2018-07-26
    • 2016-10-03
    • 1970-01-01
    • 2017-09-28
    • 2014-10-02
    • 2013-01-22
    • 2012-07-13
    相关资源
    最近更新 更多