1

I'm work on project using JavaFX and JavaCV. My main feature in app is based on webcam capture. I'm looking for a way to display frame from OpenCVFrameGrabber into JavaFX component.

I found a way to do it but I get the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(IIILjava/nio/ByteBuffer;)J
    at org.opencv.core.Mat.n_Mat(Native Method)
    at org.opencv.core.Mat.<init>(Mat.java:52)
    at org.bytedeco.javacv.OpenCVFrameConverter.convertToOrgOpenCvCoreMat(OpenCVFrameConverter.java:187)
    at org.bytedeco.javacv.OpenCVFrameConverter$ToOrgOpenCvCoreMat.convert(OpenCVFrameConverter.java:61)
    at TestJavaCV$Companion.main(TestJavaCV.kt:20)
    at TestJavaCV.main(TestJavaCV.kt)

I suspect that the application is not working due to not dependency failure. Probably I should provide additional libs for org.opencv.core but I don't know how to achieve this in gradle.

Minimal, Reproducible Example:

build.gradle

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.bytedeco', name: 'javacv-platform', version: '1.5.3'
}

TestJavaCV.kt

import javafx.scene.image.Image
import org.bytedeco.javacv.Frame
import org.bytedeco.javacv.OpenCVFrameConverter
import org.bytedeco.javacv.OpenCVFrameGrabber
import org.opencv.core.Mat
import org.opencv.core.MatOfByte
import org.opencv.imgcodecs.Imgcodecs
import java.io.ByteArrayInputStream

class TestJavaCV {
    companion object {
        private val toOrgOpenCvCoreMat = OpenCVFrameConverter.ToOrgOpenCvCoreMat()

        @JvmStatic
        fun main(args: Array<String>) {
            val grabber: OpenCVFrameGrabber = OpenCVFrameGrabber(0);
            grabber.start()

            val frame: Frame = grabber.grabFrame()
            val mat: Mat = toOrgOpenCvCoreMat.convert(frame)
            val matOfByte: MatOfByte = MatOfByte()

            Imgcodecs.imencode(".png", mat, matOfByte)
            val image = Image(ByteArrayInputStream(matOfByte.toArray()))
        }
    }
}
wojciech_cichocki
  • 199
  • 1
  • 3
  • 13
  • 1
    UnsatisfiedLinkError usually means you are missing a driver, not a class. It is likely the call to Mat.n_Mat() is to a native driver that is not available. This probably is not a JAR, but more likely a missing DLL or SO. – JoshDM Jul 23 '20 at 14:38
  • 1
    Please check https://stackoverflow.com/questions/42569126/java-lang-unsatisfiedlinkerror-org-opencv-core-mat-n-matiiij - this is a very similar issue and shows how the driver is loaded. – JoshDM Jul 23 '20 at 14:40
  • I read your references. In project I have a requirement for the application to work on Windows 10, Linux and MacOS. I wonder if it is possible to use gradle instead of providing the path to lib. – wojciech_cichocki Jul 23 '20 at 14:50
  • Another question: where is located openCV to use Load by path if I'm using gradle. ```System.load("my/full/path/native.dll");``` – wojciech_cichocki Jul 23 '20 at 14:59
  • If openCV is installed on your system, you should have a DLL to reference. You would need to check the openCV docs. From the referenced question, they suggest this `System.load("fullPathTo/opencv.dll");` - you need to find out where opencv.dll is installed on your system. "fullPathTo" is just a placeholder for the actual path. – JoshDM Jul 23 '20 at 16:59
  • Maybe this other question can help you: https://stackoverflow.com/questions/17767557/how-to-use-opencv-in-using-gradle – JoshDM Jul 23 '20 at 17:01
  • BTW, it's easier to get this work with [Gradle JavaCPP](https://github.com/bytedeco/gradle-javacpp#getting-started). See https://github.com/bytedeco/gradle-javacpp/tree/master/samples/javacv-demo – Samuel Audet Oct 16 '20 at 01:08

1 Answers1

1

This question java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J? answers why you are getting that UnsatisfiedLinkError; the library for OpenCV is not loaded by your Java VM and therefore the relevant native calls cannot be made.

This question How to use opencv in using Gradle? should help you with configuring OpenCV using Gradle.

Per your comment question "I have a requirement for the application to work on Windows 10, Linux and MacOS." I don't know how to solve that using gradle, however in Java I would inject a different system property per o/s and use that in a static block in your class to load your library:

static {

    String libraryPath = System.getProperty("opencv.path");

    System.load(libraryPath);

}
JoshDM
  • 4,939
  • 7
  • 43
  • 72
  • In the case of JavaCV, it's easier to just call `Loader.load(opencv_java.class)` as documented here: https://github.com/bytedeco/javacpp-presets/tree/master/opencv#documentation – Samuel Audet Oct 16 '20 at 01:09