所以Java now...有OpenCV! 谁能告诉我如何用它打开Videofiles?
我试着看一遍互联网,但一无所获。 VideoCapture类的文档不是很有用,因为它提供了一个C#示例并展示了如何从网络摄像头捕获。
Q&A of OpenCV也没有帮助,因为没有(公共)方法可以为其提供文件名字符串。
但它应按照API中的说明工作。但事实并非如此 但是,VideoCapture类中有一个带有sting参数的privte方法。
请回答是否有解决方案,或者即使您遇到同样的问题。 garyee
更新:( 2017年5月)
从3.0.0版开始,VideoCapture类的构造函数接受一个字符串参数。所以现在可以轻松解决这个问题!
答案 0 :(得分:5)
对我而言,为什么所谓的自动生成的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 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,它应该可以工作。
答案 1 :(得分: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变量
答案 2 :(得分: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 :(得分: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;
}
&#13;