Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Java wrappers for OpenCV Text module

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 haps 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 for this case. Any ideas or help would be very much appreciated.

Java wrappers for OpenCV Text module

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 createERFilterNM1(const String& filename, 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 createERFilterNM2(const String& filename, 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 haps 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 for this case. Any ideas or help would be very much appreciated.

Java wrappers for OpenCV Text module

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 haps 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 for this case. Any ideas or help would be very much appreciated.

Java wrappers for OpenCV Text module

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 for this case. Any ideas or help would be very much appreciated.

The generated java wrappers below:

public class ERFilter {

    protected final long nativeObj;
    protected ERFilter(long addr) { nativeObj = addr; }


    @Override
    protected void finalize() throws Throwable {
        delete(nativeObj);
    }



    // native support for java finalize()
    private static native void delete(long nativeObj);

}

.... the detectRegions() method as generated in the module class (Text.java):

public static void detectRegions(Mat image, ERFilter er_filter1, ERFilter er_filter2, List<MatOfPoint> regions)
{
    Mat regions_mat = new Mat();
    detectRegions_0(image.nativeObj, er_filter1.nativeObj, er_filter2.nativeObj, regions_mat.nativeObj);
    Converters.Mat_to_vector_vector_Point(regions_mat, regions);
    regions_mat.release();
    return;
}

... and and the corresponding JNI method in Text.java:

private static native void detectRegions_0(long image_nativeObj, long er_filter1_nativeObj, long er_filter2_nativeObj, long regions_mat_nativeObj);