Ask Your Question

SURF/SIFT Java wrapper for OpenCV 3.x/OSX 10.11

asked 2016-09-05 02:19:41 -0500

jcrist gravatar image

Sorry for my lame question, I'm still new to OpenCV. I'm trying to compile OpenCV 3.1 with SURF/SIFT support from the git master. It looks like there is no way I can access these algorithms from Java so after some research I decided to follow recommendations as stated in this article.

Unfortunately no luck - the make goes well but I'm getting linker error at the very last step as follows:

[ 80%] Linking CXX shared library ../../lib/libopencv_java310.dylib Undefined symbols for architecture x86_64: "cv::xfeatures2d::SIFT::create(int, int, double, double, double)", referenced from: cv::javaFeatureDetector::create(int) in features2d.cpp.o cv::javaDescriptorExtractor::create(int) in features2d.cpp.o "cv::xfeatures2d::SURF::create(double, int, int, bool, bool)", referenced from: cv::javaFeatureDetector::create(int) in features2d.cpp.o cv::javaDescriptorExtractor::create(int) in features2d.cpp.o

Any ideas how to fix this would be very much appreciated.

edit retag flag offensive close merge delete


Are you sure it is not in? Latest docs still tell it is there:

StevenPuttemans gravatar imageStevenPuttemans ( 2016-09-05 04:17:00 -0500 )edit

It is not. for example FeatureDetector.create(FeatureDetector.SURF) will throw exception (illegal argument). Java wrapper has SIFT and SURF cases commented in the code as well (opencv/modules/features2d/misc/java/src/cpp/features2d_manual.hpp). Now these methods are in opencv_contrib xfeatures2d module. I'm compiling it with OPENCV_ENABLE_NONFREE=ON and it looks like it is compiling and linking just fine, with no errors. It also creates libopencv_xfeatures2d.3.1.dylib in the /usr/local/lib after make & make install as it should. But the libopencv_java310.dylib is not linking - it says references to SIFT and SURF create methods are undefined.

jcrist gravatar imagejcrist ( 2016-09-05 04:29:43 -0500 )edit

do you understand, that opencv_xfeatures2d is not linked, when compiling the java wrappers ? (it's not done by default, you're somewhat off-the-grid here. probably needs fiddling with cmake stuff.)

also, sad as it is, i would not give 2ct. for stackoverflow answers considering opencv...

berak gravatar imageberak ( 2016-09-05 12:36:58 -0500 )edit

Thank you berak, that is what I thought - opencv_xfeatures2d is not in the dependency list for opnecv_java310 so no wonder there is a link problem.

Agree that the stackoverflow answer is probably not the best option here as it leads to "illegal" forking of the opencv library (illegal in a sense that it goes against the idea of placing all non-free and experimental methods in a separate repository). So I guess my question can be transformed to this: if hacking opencv java wrapper is not the best option then what is the recommended way of accessing nonfree methods from java?

jcrist gravatar imagejcrist ( 2016-09-05 23:59:14 -0500 )edit

it's only illegal, if you want to sell your software containing nonfree modules.

for now, i think, you'll have to hack it, just "more successful". you've introduced a circular dependancy between features2d and xfeatures2d, and xfeatures2d has to be added to the java dependancies.

in the long run,-- the whole way those feature2d classes are wrapped are an ugly leftover from opencv2.4, which could not handle cv::Ptr correctly, and someone wrote a chunky workaround. this all has to go away.

whish, i could help better, but no java her, atm, so i cannot test !

berak gravatar imageberak ( 2016-09-06 01:45:03 -0500 )edit

Found a bit more elegant way to build the java wrappers on contrib modules.

basically it boils down to changing the CMakeLists.txt as described here.

This is also applicable to any contrib module, not only xfeatures2d with nonfree modules. However there are 2 issues: 1. The java wrappers do not compile unless necessary imports from org.opencv.features2d added. One can workaround this by adding necessary imports to java classes manually and then repeating the build. 2. The resulting wrapper seems to be not working. For example I can create SIFT feature detector (SURF.create() works fine) but calling SURF.detect(Mat, MatOfkeypoint) crashes java (((. Any idea what this could be?

jcrist gravatar imagejcrist ( 2016-09-18 09:12:19 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2016-09-23 13:12:21 -0500

jcrist gravatar image

updated 2016-09-26 10:04:29 -0500

I've made some progress in resolving this issue. Making changes as described here leads to generation of java wrappers for SIFT and SURF - opencv-310.jar has org.opencv.xfeatures2d package now. Some fix was required in /opencv/modules/java/generator/ Namely inserted 2 lines as shown below:

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

After these changes wrappers are generated successfully. However the main problem still remains, how to use these wrappers from Java )). For example SIFT.create() gives the pointer to a new SIFT class but calling any class method (for instance detect()) crashes Java. I also noticed that using MSER.create() directly from Java leads to the same crash.

So it looks like the problem is isolated to the way how Feature2D.create() methods are wrapped in Java. The solution seems to be the following (again, changing /opencv/modules/java/generator/

Find the string:

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

Replace it with the following:

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

Rebuild the opencv. That is it, all create() methods will start working properly for all children of Feature2D class including experimental and non-free methods. FeatureDescriptor/DescriptorExtractor wrappers can be deprecated I think as Feature2D is much easier to use.

BUT! I'm not sure if the suggested fix is safe for other OpenCV modules. Is there a scenario when (jlong)curval needs to be dereferenced? It looks like the same fix was suggested already here.

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2016-09-05 02:19:41 -0500

Seen: 2,299 times

Last updated: Sep 26 '16