How to use OpenCV 4 in Java on Raspberry PI (armv6 and armv7 Raspian)?

7

This question is very similar to this one however it's on Linux ARM ( Raspberry Pi).

I've compiled OpenCV 4.4.0 from source along with the Java bindings and tried something like this hack (that worked on Windows):

import org.opencv.core.*;

public class CVTest {

        public static void main(String[] args) {
                System.out.println("setup");
//              loading the typical way fails :(
//              System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

                System.load("/home/pi/eclipse/CVTest/lib/libopencv_core.so");
////System.load("/home/pi/opencv/build/lib/libopencv_core.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_imgproc.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_imgcodecs.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_img_hash.so");
////System.load("/home/pi/eclipse/CVTest/lib/opencv_core.so");//videoio_ffmpeg440_64.dll
//System.load("/home/pi/eclipse/CVTest/lib/libopencv_videoio.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_photo.so");

System.load("/home/pi/eclipse/CVTest/lib/libopencv_xphoto.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_flann.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_features2d.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_calib3d.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_phase_unwrapping.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_structured_light.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_xfeatures2d.so");

System.load("/home/pi/eclipse/CVTest/lib/libopencv_video.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_ximgproc.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_aruco.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_bgsegm.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_bioinspired.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_objdetect.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_face.so");

System.load("/home/pi/eclipse/CVTest/lib/libopencv_dnn.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_tracking.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_plot.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_ml.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_ml.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_text.so");
// crashes here!
System.load("/home/pi/eclipse/CVTest/lib/libopencv_java440.so");


Mat m = Mat.eye(new Size(3,3), CvType.CV_8UC1);
                System.out.println("done");
        }
        
}

However, depending on the Raspberry Pi, I get different crashes at the same line, loading libopencv_java440 (after the other dependant libraries have loaded):

On a Raspberry Pi 3B running Raspian stretch I get errors like this one:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGBUS (0x7) at pc=0x6360f644, pid=9730, tid=0x64eba470
#
# JRE version: Java(TM) SE Runtime Environment (8.0_202-b08) (build 1.8.0_202-b08)
# Java VM: Java HotSpot(TM) Client VM (25.202-b08 mixed mode linux-arm )
# Problematic frame:
# C  [libopencv_core.so+0x258644]  cv::Ptr<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::~Ptr()+0x38
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x76162400):  VMThread [stack: 0x64e3b000,0x64ebb000] [id=9733]

siginfo: si_signo: 7 (SIGBUS), si_code: 1 (BUS_ADRALN), si_addr: 0x7c1f010e

Registers:
  r0  = 0x636e6270
  r1  = 0x00000000
  r2  = 0x000011f8
  r3  = 0x7c1f010e
  r4  = 0x7c1f00f2
  r5  = 0x636e6270
  r6  = 0x76ee84ac
  r7  = 0x00000001
  r8  = 0x6470c600
  r9  = 0x000003ec
  r10 = 0x000003ec
  fp  = 0x64eb9c0c
  r12 = 0x76fa4ce4
  sp  = 0x64eb9be8
  lr  = 0x76ddadd4
  pc  = 0x6360f644
  cpsr = 0x20000010

Top of Stack: (sp=0x64eb9be8)
0x64eb9be8:   76ee8000 00000000 76ee84ac 76ddadd4
0x64eb9bf8:   76129d7c 76ddae34 00000000 76635d7c
0x64eb9c08:   64eb9c2c 768ac3dc 76162270 63736954
0x64eb9c18:   76940000 76129988 76129990 76129d7c
0x64eb9c28:   64eb9ca4 768aaa54 7696a050 76942d14
0x64eb9c38:   64eb9ca4 767f8084 00000000 00000000
0x64eb9c48:   8c365cd8 00000000 76909901 76966044
0x64eb9c58:   76163208 00000000 00000000 7696a050

Instructions: (pc=0x6360f644)
0x6360f624:   0a00000d e59f20c4 e7933002 e3530000
0x6360f634:   0a00000b e284301c ee070fba e1932f9f
0x6360f644:   e2421001 e1830f91 e3500000 1afffffa
0x6360f654:   e3520001 ee070fba 0a00000f e1a00005

Register to memory mapping:

  r0  = 0x636e6270

On a Raspberry Pi ZeroW also running Raspian Stretch I a beefy log: example.

Any tips on getting OpenCV Java bindings to work on arvm6/armv7 CPUs ?

Update Thanks to the comment from @Catree I've ran the tests as well. As you can see in opencv_cpp_tests.txt mosts tests run, excluding ones where asset loading is required (Must've botched running the asset part).

I did try running the Java tests as well, however I'm missing something obvious because the java.library.path argument I pass to the lib folder containing opencv's shared libraries doesn't seem to work. You can view the output in opencv_java_tests.txt

I've also tried the old-school 2.4 Introduction to Java Development OpenCV Tutorial specifying the correct java class paths and library path, but got greeted by a segfault :/

java -Djava.library.path=/home/pi/opencv/build/lib -classpath /home/pi/opencv/build/bin/opencv-440.jar:/home/pi/opencv/build/build/jar/SimpleSample.jar SimpleSample -verbose
Segmentation fault

Any hints/tips to progress are greatly appreciated

Update 2 Following @moyeen52's advice I've compiled OpenCV static libs (-DBUILD_SHARED_LIBS=OFF) and noticed libopencv_java.so goes from 2.1MB to 31MB. Unfortunately I still get the same segfault :(

I also had a look at the other post which unfortunately doesn't apply as OpenCV compiles libopencv_java440.so already (no need to rename).

Update 3 To ease testing for anyone out there with a Raspberry PI 3 B+ I've uploaded the following:

  • HelloCV.tar.gz: contains Hello.java (which simply tried to load the library, create a Mat and print it), opencv-440.jar, libopencv_java440.so (static build) and compile.sh and run.sh which should call javac/java with the right arguments, locally referencing the java and c++ libraries.
  • opencv440_static_rpi3b.tar.gz: static library build
  • opencv440_shared_rpi3b.tar.gz: shared library build

Additionally I will try recompiling without libatomic nor NEON and VPF3 CPU optimisations and will post updates

Your advice/tips are very much appreciated ! Thank you

java
opencv
raspberry-pi
arm
asked on Stack Overflow Jun 22, 2020 by George Profenza • edited Jul 4, 2020 by George Profenza

1 Answer

2

Thank you everyone for the comments: they have been instrumental in narrowing down the issue and finding a solution.

The c++ errors might hava been due to the difference between C++ compilers (and support for c++ 11 or higher). Although I found a few resources on updating g++ (from 6.3.0 to 8.3.0) I didn't want to risk running into other issues.

I've used completely fresh installs of Raspian OS (Buster) for each system (PiZeroW (armv6) and Pi3B+ (armv7)) which worked with no issues at all. Additionally I've used OpenJDK 8 instead of 11 for my project needs.

I have stored prebuild binaries (full contents of the install folder) here:

Additionally, there are minimal zips for the java wrapper with a Hello world test and compile/run bash scripts:

(Note the Java wrapper is compiled with OpenJDK 8)

answered on Stack Overflow Jul 13, 2020 by George Profenza

User contributions licensed under CC BY-SA 3.0