Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 258
George Profenza Avatar asked Jun 22 '20 00:06

George Profenza


People also ask

Can I run OpenCV on Raspberry Pi?

By default, OpenCV uses ARMv7 instruction set as a minimal baseline — it is a modern architecture and enables the execution on a wide spectrum of hardware. Old Raspberry Pi 1 and Raspberry Pi Zero use older ARMv6 architecture and do not have much scope for acceleration. Your Raspberry may well support more than ARMv7 baseline.

What does OpenCV do for arm?

The OpenCV library provides an integration with several ARM-specific acceleration libraries. OpenCV HAL (Hardware Abstraction Layer) is an interface for platform-specific and low-level architecture-specific implementations. OpenCV contains NVIDIA Carotene — it implements HAL for ARMv7 and ARMv8 architectures and uses NEON instructions.

What is the best way to install OpenCV?

Compiling from source (takes longer, but gives you the full OpenCV install/optimizations) The pip method to install OpenCV 4 is by far the easiest way to install OpenCV (and the method I recommend for 90% of projects). It is especially great for beginners too. If you need the full install of OpenCV, you must compile from source.

How to capture live video feed from OpenCV using Python?

Check to see which version of OpenCV you have installed. Now, go to the Python IDE in your Raspberry Pi by clicking the logo -> Programming -> Thonny Python IDE. Write the following code to capture a live video feed.


1 Answers

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:

  • opencv_440_pi0w.tar.gz -> compiled on Raspberry Pi Zero W
  • opencv_440_pi3b.tar.gz -> compiled on Raspberry Pi 3 B+
  • opencv_440_pi4.tar.gz -> compiled on Raspberry Pi 4

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

  • HelloCVPI0W.tar.gz for armv6: tested on Raspberry Pi Zero
  • HelloCVPI3B+.tar.gz for armv7: tested on Raspberry Pi 3 B+
  • HelloCVPI4.tar.gz for armv7: tested on Raspberry Pi 4

(Note the Java wrapper is compiled with OpenJDK 8)

like image 131
George Profenza Avatar answered Oct 03 '22 06:10

George Profenza