SURF和SIFT算法在OpenCV 3.0 Java中无法使用。

9
我正在使用最新版本的Java OpenCV 3.0,但是当我使用SURF算法或SIFT算法时,它无法正常工作并抛出异常,异常信息为:OpenCV Error: Bad argument (Specified feature detector type is not supported.) in cv::javaFeatureDetector::create 我已经搜索过Google,但是给出这种问题的答案并没有解决我的问题。如果有人知道这个问题,请告诉我。
谢谢!
更新:第三行下面的代码抛出异常。
        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);

你能发布一下你目前为止做的吗? - rslemos
这是OpenCV Java包装器中的错误,不是您的错。即使您获得了OpenCV_contrib存储库(其中移动了SURF代码)并构建了它,opencv/modules/features2d/misc/java/src/cpp/features2d_manual.hpp第155行的代码也不允许您使用它。 - berak
谢谢您的快速回复!根据您的评论,我理解在Java中没有办法使用这两个算法,是吗?如果是的话,这意味着所有使用OpenCV和Java的人都会遇到这个普遍问题,那么为什么OpenCV团队不解决这个错误。昨天OpenCV发布了3.0版本,那么我们要等多久才能看到OpenCV团队解决这个问题。顺便问一下,您能告诉我其他在Java中运行良好的算法吗(像FAST、STAR等)因为我对这些算法还很陌生。谢谢! - Bahramdun Adil
3个回答

10

如果您从源代码编译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后,请记得重新复制.jar和.dll(或.so)以在Java项目中使用! - Lake
非常感谢!那真的很有帮助。 - Bahramdun Adil
我加入了fd = xfeatures2d :: SURF :: create();,代替我刚刚删除的“name = name +” SIFT“!重点是要填充'fd'和'de'变量,这样它就可以正常运行^^ - Lake
1
在配置 CMake GUI 时,您必须将 OPENCV_EXTRA_MODULES_PATH 设置为您的 OpenCV Contrib 项目路径下的 <opencv_contrib>/modules! - Lake
在Windows中遇到了相同的问题,即未生成opencv_java310.dll...我怀疑这是由于一个错误“fatal error C1083: Cannot open include file: 'opencv2/xfeatures2d.hpp': No such file or directory (features2d.cpp)”在之前发生了。 - Thushar G R
显示剩余14条评论

8
那是因为在OpenCV的新版本(3+)中它们不再免费。我曾经遇到过这个问题。你需要:
  1. 下载OpenCV(如果你还没有)
  2. opencv github仓库下载非免费部分
  3. 使用cmake -DBUILD_SHARED_LIBS=OFF命令生成makefiles,并使用DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules选项指定非免费部分,然后使用make -j8(或者你使用的其他Java版本)进行构建
  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非免费部分

你知道如何在Android Studio中生成CMake文件吗? - Chirag Solanki
1
谢谢您的帖子。我下载了4.1.0版本,而且我只需要运行cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DOPENCV_ENABLE_NONFREE=ON -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules..,无需编辑任何源代码。 - Juan

1

我认为将features2d模块(FeatureDetector类或features2d_manual.hpp中的任何其他类)更改为启用来自OpenCV contrib模块的方法是一种不太有吸引力的方法,因为它会导致“核心”OpenCV和扩展之间的循环依赖关系(可能是非免费或实验性的)。 有另一种方法可以解决此问题,而不影响feature2d类。按照here所述在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。这样,所有Feature2D类的子类,包括实验性和非免费方法,都将正常工作。我认为可以弃用FeatureDescriptor / DescriptorExtractor包装器,因为Feature2D更容易使用。
但是!我不确定建议的修复是否对其他OpenCV模块安全。是否存在需要取消引用(jlong)curval的情况?看起来已经在此处建议了相同的修复。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接