对我来说,为什么所谓的 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-constructor 已在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,它应该可以工作。