javaopencvkotlingradlejavacv

java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(IIILjava/nio/ByteBuffer;)J


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()))
        }
    }
}

Solution

  • 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);
    
    }