'OpenCV Android React Native unknown exception on some functions in imgproc module

I'm trying to use OpenCV in an mobile app written with React Native. For now i only focus on the Android part. I use the official OpenCV for Android release. I did add the sdk, modified my MainApplication.java and wrote some wrapping methods that can be called from React Native. So far this compiles and works as expected.

Now the problem is that if get an unknown exception from some OpenCV functions, others work fine. E.g. when I call the blur(), medianBlur() or warpAffine() functions from the Imgproc module everything is well. When i try to call e.g. the gaussianBlur() or Canny() functions i get an unknown exception thrown from OpenCV.

I really have no idea what the problem is. The sdk seems to be linked correctly as i can booth compile the app and run several functions.

My Setup:

  • Development on Arch Linux
  • OpenCV 4.3.0 for Android
  • React Native 0.62.2
  • Compiled with gradle/react-native from terminal
  • Android 10

Example error when i try to run the Canny() function:

org.opencv.imgproc: imgproc::Canny_12() caught unknown exception
unknown exception
java.lang.Exception: unknown exception
    at org.opencv.imgproc.Imgproc.Canny_2(Native Method)
    at org.opencv.imgproc.Imgproc.Canny(Imgproc.java:2662)
    at com.rnopencv.RNOpenCvLibraryModule.cannyEdges(RNOpenCvLibraryModule.java:110)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
    at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
    at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
    at android.os.Looper.loop(Looper.java:214)
    at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
    at java.lang.Thread.run(Thread.java:919)

calling the following wrapper:

@ReactMethod
    public void cannyEdges(String imageAsBase64, int treshold, Promise promise) {
        try {
            // Constants
            Size BLUR_SIZE = new Size(3,3);
            int KERNEL_SIZE = 3;
            int RATIO = 3;
            int MAX_LOW_THRESHOLD = 100;

            int lowTreshold = (treshold <= MAX_LOW_THRESHOLD) ? treshold : MAX_LOW_THRESHOLD;

            // decode base64 string to matrix
            Bitmap srcImage = base64ImageToBitmap(imageAsBase64);
            Mat srcMat = new Mat();
            Utils.bitmapToMat(srcImage, srcMat);

            // rotate image to be portrait
            Mat orientedMat = rotateBoxed(srcMat, -90);

            // blur the image
            Mat bluredMat = new Mat();
            Mat cannyMat = new Mat();
            Imgproc.blur(orientedMat, bluredMat, BLUR_SIZE);
            // NEXT LINE THROWS THE ERROR
            Imgproc.Canny(bluredMat, cannyMat, lowTreshold, lowTreshold * RATIO, KERNEL_SIZE, false);

            // return blured image wrapped in promise
            Bitmap dstImage = Bitmap.createBitmap(cannyMat.cols(), cannyMat.rows(), srcImage.getConfig());
            Utils.matToBitmap(cannyMat, dstImage);
            promise.resolve(bitmapToBase64(dstImage));
        } catch (Exception e) {
            System.out.println("Oh snap, some Exception occured!");
            System.out.println(e.getMessage());
            e.printStackTrace(System.out);
            promise.reject("Could not perform canny edge detection on image!", e);
        }
    }

The wrapper gets the image as base64 encoded String (don't have a better solution yet) and returns the result in a js Promise. I also rotate the image to correct orientation using an affine transformation (this part works like described above). I tried various values for threshold, same goes for the gaussianBlur() method. The result is always either an assertion failure for invalid parameters (which is expected) or the mysterious unknown exception.

Any clues on what the problem might be?

Update: When i use an older version of openCV e.g. 3.4.10 for Android it will work.



Solution 1:[1]

At last time, I faced this problem, so I chose Open CV API instead of this. I hope this help you a bit.

Solution 2:[2]

I have been working without error on opencv 4.5.2, android and react native. Than i have tried another project with same opencv version but I got same error as you mentioned. Than i realized differences between gradle version. So, i upgraded gradle version from "com.android.tools.build:gradle:3.5.2" to "com.android.tools.build:gradle:4.2.2" in app gradle.build file. Than problem solved. Long story short, update gradle version.

I hope that helps you too.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Angel Jerry
Solution 2 Canberk Atbinici