用opencv java打开video文件

所以现在有OpenCV for Java …… ! 谁能告诉我如何用它打开Videofiles?

我试着看看整个互联网,但一无所获。 VideoCapture类的文档并不是非常有用,因为它提供了一个C#示例并展示了如何从网络摄像头捕获。

OpenCV的Q&A也没有帮助,因为没有(公共)方法可以给你一个文件名字符串。

但它应该像在API中编写的那样工作。 但它没有在VideoCapture类中有一个带有sting参数的privte方法。

请回答是否有解决方案,或者即使您遇到同样的问题。 garyee

更新:(2017年5月)

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

对我而言,为什么所谓的自动生成的opencv java包装器缺乏这个function,这是一个谜。 我首先使用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.(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导出。 特别是为J​​NICALL找到合适的方法名称certificate是具有挑战性的,因为构造函数被重载并且将java类作为参数。 另外,我们需要将java sting转换为c-string。 其余的是从其他构造函数复制而来。

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

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

}

这是它对我有用的方式。

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