SURF和SIFT算法在OpenCV 3.0 Java中不起作用

我在Java中使用OpenCV 3.0(最新版本),但是当我使用SURF算法或SIFT算法时它不起作用并抛出Exception,其中说: OpenCV Error: Bad argument (Specified feature detector type is not supported.) in cv::javaFeatureDetector::create

我用谷歌搜索了,但是给出这类问题的答案并没有解决我的问题。 如果有人知道这个问题,请告诉我。

提前致谢!

更新:第三行中的代码抛出exception。

  Mat img_object = Imgcodecs.imread("data/img_object.jpg"); Mat img_scene = Imgcodecs.imread("data/img_scene.jpg"); FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF); MatOfKeyPoint keypoints_object = new MatOfKeyPoint(); MatOfKeyPoint keypoints_scene = new MatOfKeyPoint(); detector.detect(img_object, keypoints_object); detector.detect(img_scene, keypoints_scene); 

如果从源代码编译OpenCV,则可以通过自己编辑opencv / modules / features2d / misc / java / src / cpp / features2d_manual.hpp来修复缺少的绑定。

我通过进行以下更改来修复它:

 (line 6) #ifdef HAVE_OPENCV_FEATURES2D #include "opencv2/features2d.hpp" #include "opencv2/xfeatures2d.hpp" #include "features2d_converters.hpp" ...(line 121) case SIFT: fd = xfeatures2d::SIFT::create(); break; case SURF: fd = xfeatures2d::SURF::create(); break; ...(line 353) case SIFT: de = xfeatures2d::SIFT::create(); break; case SURF: de = xfeatures2d::SURF::create(); break; 

唯一的要求是你和你的源一起构建opencv_contrib可选模块(你可以从https://github.com/Itseez/opencv_contrib下载git项目,并在opencv的ccmake设置上设置它的本地路径。

哦,请记住,SIFT和SURF是非自由软件^^;

这是因为它们不适用于较新版本的OpenCV(3+)。 我不久前遇到了这个问题。 你必须:

  1. 下载OpenCV(如果还没有)
  2. 从opencv github repo下载nonfree部分
  3. 使用cmake -DBUILD_SHARED_LIBS=OFF生成makefile,使用DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules选项指定非DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules部分,并使用make -j8 (或您使用的任何Java版本) make -j8构建
  4. 编辑features2d_manual.hpp文件,包括opencv2/xfeatures2d.hpp ,包括SIFT和SURF case的必要代码,这些代码已注释且未定义: fd=xfeatures2d::SIFT::create(); 对于SIFT描述符和de = xfeatures2d::SIFT::create(); 用于SIFT提取器。 如果您也想使用SURF,请执行相同的操作。

我写这篇文章一步一步解释如何编译非自由的OpenCV部分,以便使用像SIFT或SURF这样的私有工具。 编译OpenCV非自由部分

我相信更改features2d模块(FeatureDetector类或features2d_manual.hpp中的任何其他类)来启用OpenCV contrib模块的方法是不太有吸引力的方法,因为它导致“核心”OpenCV和扩展之间的循环依赖(可以是非自由的或实验)。 还有另一种方法可以在不影响feature2d类的情况下解决此问题。 在xfeatures2d中进行更改CMakeLists.txt如此处所述导致为SIFT和SURF生成java包装器 – opencv-310.jar现在具有org.opencv.xfeatures2d包。 /opencv/modules/java/generator/gen_java.py中需要一些修复。 即插入2行,如下所示:

 def addImports(self, ctype): if ctype.startswith('vector_vector'): self.imports.add("org.opencv.core.Mat") self.imports.add("org.opencv.utils.Converters") self.imports.add("java.util.List") self.imports.add("java.util.ArrayList") self.addImports(ctype.replace('vector_vector', 'vector')) elif ctype.startswith('Feature2D'): #added self.imports.add("org.opencv.features2d.Feature2D") #added elif ctype.startswith('vector'): self.imports.add("org.opencv.core.Mat") self.imports.add('java.util.ArrayList') if type_dict[ctype]['j_type'].startswith('MatOf'): self.imports.add("org.opencv.core." + type_dict[ctype]['j_type']) else: self.imports.add("java.util.List") self.imports.add("org.opencv.utils.Converters") self.addImports(ctype.replace('vector_', '')) 

在这些更改之后,成功生成包装器。 然而,主要问题仍然存在,如何使用Java中的这些包装器))。 例如,SIFT.create()给出了指向新SIFT类的指针,但调用任何类方法(例如detect())都会导致Java崩溃。 我还注意到直接从Java使用MSER.create()会导致同样的崩溃。

所以看起来问题与Feature2D.create()方法如何用Java包装的方式是分开的。 解决方案似乎如下(再次,更改/opencv/modules/java/generator/gen_java.py):

找到字符串:

 ret = "%(ctype)s* curval = new %(ctype)s(_retval_);return (jlong)curval->get();" % { 'ctype':fi.ctype } 

将其替换为以下内容:

 ret = "%(ctype)s* curval = new %(ctype)s(_retval_);return (jlong)curval;" % { 'ctype':fi.ctype } 

重建opencv。 也就是说,所有create()方法都将开始为Feature2D类的所有子项正常工作,包括实验和非自由方法。 FeatureDescriptor / DescriptorExtractor包装器可以弃用我认为Feature2D更容易使用。

但! 我不确定建议的修复是否对其他OpenCV模块是安全的。 是否存在需要取消引用(jlong​​)curval的情况? 看起来在这里已经建议了同样的修复。