Ask Your Question
0

Java wrappers for OpenCV Text module

asked 2017-05-07 14:36:21 -0600

jcrist gravatar image

updated 2017-05-08 07:15:40 -0600

Dear OpenCV team! Need your help again and sorry for such a long question.

I'm trying to generate java wrappers for OpenCV OCR Text/Tesseract module, which is in contrib repository now. Here is what I managed so far (skipping all the trivial stuff like enabling contrib, installing tesseract etc):

  1. Changed modules/text/CMakeLists.txt, added "java".
  2. Added methods to ERFilter as follows:

    CV_EXPORTS_W Ptr<erfilter> createERFilterNM1(const String& filename, int thresholdDelta = 1, float minArea = (float)0.00025, float maxArea = (float)0.13, float minProbability = (float)0.4, bool nonMaxSuppression = true, float minProbabilityDiff = (float)0.1) { return createERFilterNM1(loadClassifierNM1(filename), thresholdDelta, minArea, maxArea, minProbability, nonMaxSuppression, minProbabilityDiff); }

    CV_EXPORTS_W Ptr<erfilter> createERFilterNM2(const String& filename, float minProbability = (float)0.3) { return createERFilterNM2(loadClassifierNM2(filename), minProbability); }

The idea was to merge interfaces loadClassifierNM1 and loadClassifierNM2 with "native" createERFilterNM1 and createERFilterNM2, respectively and get rid of necessity to wrap Ptr<erfilter::callback>& type in Java.

  1. Made ERFilter orphan - removed inheritance from Algorithm. I did not get the reason why it has to be inherited. The side effect of inheritance was - when java wrapper is handling method argumenths of type Ptr_* (like in the function detectRegions), it actually passes nativeObj field through JNI C wrapper. This field is declared as protected in Algorithm so it can be accessed only by children of Algorithm or by classes in the same package. Since Text is in different package and even different repository, the generation of java wrappers fails. Making ERFilter orphan helps to resolve this problem.

After these 3 steps java wrapper for Text module is generated successfully. However! This code crashes java with Exception Type EXC_BAD_ACCESS (SIGABRT):

private List<rect> findContours2(Mat img) { List<rect> boundRects = new ArrayList<rect>();

List<Mat> channels = new ArrayList<>();

Text.computeNMChannels(img, channels);

System.out.println("Extracting Class Specific Extremal Regions from "+channels.size()+" channels ...");

ERFilter erc1 = Text.createERFilterNM1(getClass().getResource(DEFAULT_CLASSIFIER_NM1).getPath(),16,0.00015f,0.13f,0.2f,true,0.1f);
ERFilter erc2 = Text.createERFilterNM2(getClass().getResource(DEFAULT_CLASSIFIER_NM2).getPath(), 0.5f);        

for(Mat channel : channels) {
    List<MatOfPoint> regions = new ArrayList<>();
    Text.detectRegions(channel, erc1, erc2, regions); // **Java fails here with Exception Type:        EXC_BAD_ACCESS (SIGABRT)**
    MatOfRect mor = new MatOfRect();
    Text.erGrouping(image, channel, regions, mor);

    for(Rect r : mor.toArray()) {
        boundRects.add(r);
    }
}

return boundRects;

}

The crash seems to be happening in JNI C layer. Here is the source generated for detectRegions method:

JNIEXPORT void JNICALL Java_org_opencv_text_Text_detectRegions_10 (JNIEnv*, jclass, jlong, jlong, jlong, jlong);

JNIEXPORT void JNICALL Java_org_opencv_text_Text_detectRegions_10
  (JNIEnv* env, jclass , jlong image_nativeObj, jlong er_filter1_nativeObj, jlong er_filter2_nativeObj, jlong regions_mat_nativeObj)
{
    static const char method_name[] = "text::detectRegions_10()";
    try {
        LOGD("%s", method_name);
        std::vector< std::vector<Point> > regions;
        Mat& regions_mat = *((Mat*)regions_mat_nativeObj);
        Mat& image = *((Mat*)image_nativeObj);
        cv::text::detectRegions( image, Ptr<cv::text::ERFilter>((cv::text::ERFilter*)er_filter1_nativeObj), Ptr<cv::text::ERFilter>((cv::text::ERFilter*)er_filter2_nativeObj), regions );
        vector_vector_Point_to_Mat( regions, regions_mat );
        return;
    } catch(const std::exception &e) {
        throwJavaException(env, &e, method_name);
    } catch (...) {
        throwJavaException(env, 0, method_name);
    }
    return;
}

It seems the Ptr pointer is used incorrectly but I can't figure out the correct way ... (more)

edit retag flag offensive close merge delete

Comments

the jni code, which creates the er_filter2_nativeObj would be interesting, too.

berak gravatar imageberak ( 2017-05-08 04:41:05 -0600 )edit

hi berak, added all components as requested. Seems like nothing extraordinary but I may be missing something ...

jcrist gravatar imagejcrist ( 2017-05-08 07:34:44 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-05-09 03:31:52 -0600

jcrist gravatar image

updated 2017-05-09 03:32:55 -0600

Ok, I've made some progress resolving this.

Assume we are to wrap a C++ method like void foo(const Ptr<t>& arg). Whenever gen_java.py meets the function parameter of type const Ptr<t>&, it generates the following JNI code:

java:

public void foo(T arg) {
      foo_0(arg.nativeObj);
      return;
}
private static native void foo_0(long arg_nativeObj);

JNI C wrapper

JNIEXPORT void JNICALL Java_org_opencv_<module>_<class>_foo_10 (JNIEnv* env, jclass jclass, jlong arg_nativeObj) {
      static const char method_name[] = "<module>::foo_10()";
      try{
             LOGD("%s", method_name);
             <module>::foo(Ptr<T>((T*) arg_nativeObj)); // NOTE: crash happens here
      } catch(const std::exception &e) {
             throwJavaException(env, &e, method_name);
      } catch (...) {
             throwJavaException(env, 0, method_name);
      }
      return;
}

The line noted above is leading to Java crash, However, if to replace it with the following, the crash is cured:

<module>::foo(*((Ptr<T> *) arg_nativeObj)); // Works fine

So I guess my question can be transformed to this: what is the scenario when we need to keep the original way of wrapping of const Ptr<t> & arg? Which modules/classes/methods use it?

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-05-07 14:36:21 -0600

Seen: 986 times

Last updated: May 09 '17