0

I'm trying to do some template matching with the Java binding of OpenCV 4.3.0 in Eclipse, but attempting to load the template image always results in this error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.imgcodecs.Imgcodecs.imread_0(Ljava/lang/String;I)J

The line of code where this exception is thrown is this:

flowerTemplate = Imgcodecs.imread("/templates/flowerpot_white.png", Imgcodecs.IMREAD_COLOR);

I have tried a number of solutions suggested on similar questions on StackOverflow and elsewhere on the internet, including:

  • Pointing at the native library folder with the "Native library location" variable in the user library definition in Eclipse.
  • Adding the native library folder location to my PATH variable.
  • Adding the native library .dll location to my PATH variable.
  • Setting up the Eclipse run configuration to add the native library folder & .dll locations to the PATH and CLASSPATH variables.
  • Loading the library with the appropriate Java code, in each of the three ways I saw it suggested, in three different places which all run before the code that throws the exception.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.load(<path_to_the_dll>);

File opencvLibrary = new File(System.mapLibraryName(Core.NATIVE_LIBRARY_NAME));
System.load(opencvLibrary.getAbsolutePath());
  • Placing the .dll in question into my source folder and every subfolder. I am running it from within Eclipse, so this is also the program's working directory.

2 Answers2

0

UnsatisfiedLinkError is a runtime exception that happens when running your Java program. So placing your file in the source folder will not work.

You need it to be available in a place that your program can find it.

See this article for example:

https://www.javaworld.com/article/2077520/java-tip-23--write-native-methods.html

In it they place the library in Linux's library path. In windows you'd similarly place it in the current directory (where you're running from) or in some shared location.

This article explains Window's dll search order: https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order

You shouldn't need to explicitly call System.loadLibrary() yourself. That's the library's responsibility.

Your problem is that OpenCV is improperly installed on your machine or inaccessible from Eclipse.

For instructions on how to make in work in Eclipse see:

Add .dll to java.library.path in Eclipse/PyDev Jython project

AminM
  • 822
  • 4
  • 11
  • The source directory is the same as the working directory when running from Eclipse, so this is something I've already tried. – Somdudewillson Jun 17 '20 at 23:41
  • No. I'm not sure why it would. – Somdudewillson Jun 17 '20 at 23:52
  • the source directly is not necessarily the same. Its generally in the bin directly. Also, I've looked at the source code.. here: https://jar-download.com/artifacts/org.openpnp/opencv/3.2.0-1/source-code/nu/pattern/OpenCV.java (not the same version but close enough) You could try turning on LogLevel.FINEST to get a nice error message saying where its trying. – AminM Jun 17 '20 at 23:53
  • by trying from the command line its easier to figure out if OpenCV is properly installed on your machine vs. properly configured in Eclipse. – AminM Jun 17 '20 at 23:54
  • 1
    Another note, the [official tutorials](https://opencv-java-tutorials.readthedocs.io/en/latest/02-first-java-application-with-opencv.html#create-a-simple-application) note that you **do** need to call System.loadLibrary() yourself. – Somdudewillson Jun 17 '20 at 23:55
  • "the source directly is not necessarily the same. Its generally in the bin directly." What is this even supposed to mean? – Somdudewillson Jun 17 '20 at 23:58
  • sorry.. mistyped. The source directory is not necessarily the same in Eclipse. Often eclipse will dump class files in the bin/ directory (that's the default behavior) But yeah. you could have set it up to be the same. – AminM Jun 18 '20 at 00:00
  • If the .dll wasn't available in the working directory, this code: `File opencvLibrary = new File(System.mapLibraryName(Core.NATIVE_LIBRARY_NAME)); System.load(opencvLibrary.getAbsolutePath());` would throw an error. – Somdudewillson Jun 18 '20 at 00:03
  • Anyway.. take a look at this example: https://jar-download.com/artifacts/org.openpnp/opencv/3.2.0-1/source-code/nu/pattern/OpenCV.java See if that helps. I think its lame that the library doesn't load itself in a static initializer. But maybe they have a good reason for that. – AminM Jun 18 '20 at 00:03
  • I don't know. I'm running out of ideas. Maybe the exact version of the method you are calling in the dll: org.opencv.imgcodecs.Imgcodecs.imread_0(Ljava/lang/String;I)J Is not compatible with what the Java code is calling? Ie. there's a version mismatch? – AminM Jun 18 '20 at 00:08
  • Looking here it seems to match. So its unclear why its failing if its loading successfully. https://jar-download.com/artifacts/org.openpnp/opencv/3.2.0-1/source-code/org/opencv/imgcodecs/Imgcodecs.java – AminM Jun 18 '20 at 00:15
  • After fixing several compilation errors, over a dozen warnings, and the fact that the Logger didn't actually log **to** anything, I got that "OpenCV" class to log that it... `"FINEST: Loaded existing OpenCV library "opencv_java430" from library path."` – Somdudewillson Jun 18 '20 at 00:22
  • Then it means its autoloading in spite of what the tutorials say. What happens if you don't load explicitly at all? Does the code still fail? You can print the java.library.path environment variable to figure out what its using. Some progress! – AminM Jun 18 '20 at 00:27
  • 1
    To get that to display I had to _manually_ call the OpenCV.loadShared(); method. – Somdudewillson Jun 18 '20 at 00:31
  • Here's another article that seems to be related to this problem: https://stackoverflow.com/questions/49581404/java-programming-opencv-unsatisfied-link-error – AminM Jun 18 '20 at 04:31
0

After removing every load method and then adding them back one-by-one, I determined that the issue was most likely caused by Eclipse loading the native library folder twice.