I am using OpenCV 3.0 (the latest version) in Java, but when I use SURF algorithm or SIFT algorithm it doesn\'t work and throws Exception which says: OpenCV Error: Bad
I believe changing features2d module (FeatureDetector class or any other classes from features2d_manual.hpp) to enable methods from OpenCV contrib modules is less attractive approach because it leads to circular dependency between the "core" OpenCV and extensions (which can be non-free or experimental). There is another way to fix this issue without affecting feature2d classes. Making changes in xfeatures2d CMakeLists.txt 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/gen_java.py. Namely inserted 2 lines as shown below:
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_', ''))
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/gen_java.py):
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.