java 用opencv java打开视频文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17401852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
open video file with opencv java
提问by garyee
so there is OpenCV for Java now...! Can anyone tell me how to open Videofiles with it ?
所以现在有用于Java 的OpenCV ......!谁能告诉我如何用它打开视频文件?
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.
我尝试在互联网上查看所有内容,但一无所获。VideoCapture 类的文档不是很有帮助,因为它提供了一个 C# 示例并展示了如何从网络摄像头捕获。
the Q&A of OpenCVdoesnt help either, because there is no (public) method to whom you can give a filename string.
OpenCV的问答也无济于事,因为没有(公共)方法可以为您提供文件名字符串。
BUT it shouldwork as written in the API. But it doesn't There is however a privte method in the VideoCapture class with a sting parameter.
但它应该像 API 中写的那样工作。但是它没有但是 VideoCapture 类中有一个带有 sting 参数的 privte 方法。
please answer if have a solution, or even if you have the same problem. garyee
如果有解决方案,或者即使您有同样的问题,请回答。加里
UPDATE: (May 2017)
更新:(2017 年 5 月)
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!
从版本 3.0.0 开始,VideoCapture 类有一个接受字符串参数的构造函数。所以现在这个问题有一个简单的解决方案!
回答by mirel7c3
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:
对我来说,为什么所谓的 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)
This indicates that the corresponding JNIEXPORT is missing. Luckily this can be fixed.
这表明缺少相应的 JNIEXPORT。幸运的是,这可以解决。
Surprisingly the needed c-constructor is already defined in opencv-2.4.6/modules/highgui/include/opencv2/highgui/highgui.cpp
令人惊讶的是,所需的 c 构造函数已经在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:
我们在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;
}
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.
关键且棘手的步骤是添加 jni 导出。尤其是为 JNICALL 找到正确的方法名称被证明是具有挑战性的,因为构造函数被重载并接受一个 java 类作为参数。此外,我们需要将 java 字符串转换为 c 字符串。其余部分是从其他构造函数中复制的。
In opencv-2.4.6/modules/java/generator/src/cpp/VideoCapture.cppwe add this new JNIEXPORT:
在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;
}
}
Recompile OpenCV and it should work.
重新编译 OpenCV,它应该可以工作。
回答by WALI
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
如果您使用的是 Windows,请将 C:\opencv\build\x86\vc11\bin 添加到 Path 变量
回答by TheoreticallyNick
If you are using the new version of Java, this is how I got it to work.
如果您使用的是新版本的 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;
}
}
}
回答by adityah
Here is how it worked for me.
这是它对我的工作方式。
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;
}