Ошибка: java.lang.UnsatisfiedLinkError с калибровкой камеры Charuco (параметры детектора)

Доброе утро всем. В настоящее время я работаю над проектом, в котором мне нужно с высокой точностью определять координаты объекта на изображении. Я пробовал использовать обычную шахматную доску для калибровки камеры, но ошибка перепроецирования была слишком большой, поэтому я решил использовать калибровочный шаблон Чаруко. Я работаю с OpenCv 3.4 и Java (ограничение проекта). Поскольку функция Aruco не включена в OpenCv для Java, я создал в своем проекте новый пакет, который включает необходимые классы. Код Aruco можно найти по следующей ссылке: Код Aruco на Github

Код, который я выполняю, следующий:

protected void captureImagesCharuco() {
    int squaresX = 5;
    int squaresY = 7;
    float squareLength = (float) 37.0;
    float markerLength = (float) 22.0;
    int calibrationFlags = 0;
    float aspectRatio = 1;
    DetectorParameters detectParams = DetectorParameters.create();
    detectParams.set_adaptiveThreshWinSizeMin(3);
    detectParams.set_adaptiveThreshWinSizeMax(23);
    detectParams.set_adaptiveThreshWinSizeStep(10);
    detectParams.set_adaptiveThreshConstant(7);
    detectParams.set_minMarkerPerimeterRate(0.03);
    detectParams.set_maxMarkerPerimeterRate(4.0);
    detectParams.set_polygonalApproxAccuracyRate(0.05);
    detectParams.set_minCornerDistanceRate(10);
    detectParams.set_minDistanceToBorder(3);
    detectParams.set_minMarkerDistanceRate(0.05);
    detectParams.set_cornerRefinementWinSize(5);
    detectParams.set_cornerRefinementMaxIterations(30);
    detectParams.set_cornerRefinementMinAccuracy(0.1);
    detectParams.set_markerBorderBits(1);
    detectParams.set_perspectiveRemovePixelPerCell(8);
    detectParams.set_perspectiveRemoveIgnoredMarginPerCell(0.13);
    detectParams.set_maxErroneousBitsInBorderRate(0.04);
    detectParams.set_minOtsuStdDev(5.0);
    detectParams.set_errorCorrectionRate(0.6);
    Dictionary dictionary = Aruco.getPredefinedDictionary(0);
    CharucoBoard charucoBoard = CharucoBoard.create(squaresX, squaresY, squareLength, markerLength, dictionary);
    List<List<Mat>> charucoCorners = new ArrayList<>();
    List<Mat> charucoIds = new ArrayList<>();
    List<Mat> validImgs = new ArrayList<>();
    Size imgSize = new Size();
    int nFrame = 0;
    
    File[] listImages = imageDirectory.listFiles();
    for(File file : listImages) {
        String src = file.getAbsolutePath();
        Mat imgRead = Imgcodecs.imread(src,Imgcodecs.IMREAD_COLOR);
        imgSize = imgRead.size();
        Mat imgCopy = new Mat();
        Mat ids = new Mat();
        List<Mat> rejectedCorners = new ArrayList<>();
        List<Mat> corners = new ArrayList<>();
        if (!imgRead.empty()){ 
            Aruco.detectMarkers(imgRead, dictionary, corners, ids);
            Aruco.refineDetectedMarkers(imgRead, (Board)charucoBoard, corners, ids, rejectedCorners);
            Mat currentCharucoCorners = new Mat();
            Mat currentCharucoIds = new Mat();
            int idsSize = ids.rows()*ids.cols();
            if(idsSize>0) {
                Aruco.interpolateCornersCharuco(corners, ids, imgRead, charucoBoard, currentCharucoCorners, currentCharucoIds);
            }
            imgRead.copyTo(imgCopy);
            if(idsSize<0) {
                Aruco.drawDetectedCornersCharuco(imgCopy, currentCharucoCorners);
            }
            if(currentCharucoCorners.total()>0) {
                Aruco.drawDetectedCornersCharuco(imgCopy, currentCharucoCorners, currentCharucoIds, new Scalar(255,0,0));
            }
            charucoCorners.add(corners);
            charucoIds.add(currentCharucoIds);
            validImgs.add(imgRead);
            nFrame++;
        }
        
    }
    
    intrinsic.put(0, 0, 1);
    intrinsic.put(1, 1, 1);
    List<Mat> allCharucoCorners = new ArrayList<>();
    List<Mat> allCharucoIds = new ArrayList<>();
    for(int i =0;i<nFrame;i++) {
        Mat currentCharucoCorners = new Mat();
        Mat currentCharucoIds = new Mat();
        Aruco.interpolateCornersCharuco(charucoCorners.get(i), charucoIds.get(i), validImgs.get(i), charucoBoard, currentCharucoCorners, currentCharucoIds,intrinsic,distCoeffs,4);
        allCharucoCorners.add(currentCharucoCorners);
        allCharucoIds.add(currentCharucoIds);
    }
    double repError = Aruco.calibrateCameraCharuco(allCharucoCorners, charucoIds, charucoBoard, imgSize, intrinsic, distCoeffsCharuco, rvecs, tvecs, calibrationFlags);
    System.out.println("reprojection error : " + repError);
}

Затем я просто выполняю captureImagesCharuco () в основной программе. Однако когда я это сделаю, я получаю следующую ошибку:

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.UnsatisfiedLinkError: application.DetectorParameters.create_0()J
at application.DetectorParameters.create_0(Native Method)
at application.DetectorParameters.create(DetectorParameters.java:24)
at application.CameraCalibrate.captureImagesCharuco(CameraCalibrate.java:115)
at application.Main.main(Main.java:64)
... 11 more
Exception running application application.Main

Я попытался найти, как решить эту ошибку (UnsatisfiedLinkError), и обнаружил, что она обычно возникает, когда вы используете библиотеку, которая не включена в путь сборки или проект (хотя я не уверен). Я предполагаю, что рассматриваемая здесь библиотека - это пакет Aruco, но я не знаю, как включить пакет в путь сборки проекта.

Любая помощь будет приветствоваться! Спасибо ! :)


person HichamM    schedule 22.07.2020    source источник
comment
Я предполагаю, что вы используете какой-то собственный пакет opencv. Вы пробовали собрать opencv из исходного кода с этим выбранным пакетом? Я считаю, что в этом случае будет создан java-пакет со связанными функциями (docs.opencv.org/3.4/d9/d52/tutorial_java_dev_intro.html)   -  person Dmitrii Z.    schedule 22.07.2020
comment
Спасибо за ваш ответ ! Я считаю, что вы правы, после некоторого покопания выяснилось, что модуль, который я пытаюсь использовать, является частью библиотеки opencv-contrib, поэтому мне нужно правильно собрать его с помощью Cmake. Я еще не делал этого, но в настоящее время работаю над этим (оказывается, это немного ерунда, чтобы делать это в Windows), я опубликую об этом, если это сработает.   -  person HichamM    schedule 22.07.2020
comment
Скорее всего, для java есть готовые пакеты contrib (например, это может быть? ), но рекомендуется создать его самостоятельно.   -  person Dmitrii Z.    schedule 22.07.2020
comment
Спасибо за ссылку. Мне потребовалось некоторое время, чтобы ответить, потому что я хотел попробовать создать его самостоятельно, но это был настоящий ад, и я работал над ним со вчерашнего дня безрезультатно, поэтому я сдался, поэтому я использовал предварительно созданную библиотеку, которую вы мне дали . Это решило мою проблему, так что еще раз спасибо! :)   -  person HichamM    schedule 23.07.2020


Ответы (1)


Ошибка указывает на то, что у вас есть пакет opencv без специального модуля, который вы используете;

Чтобы исправить это, вам нужно либо найти предварительно созданный opencv с нужным вам модулем (в вашем конкретном случае он находится в библиотеке contrib, поэтому это, вероятно, поможет.

Если вы хотите собрать его из исходников - вы должны включить нужный модуль в свойствах cmake. Для contrib - вам нужно сначала создать проект cmake contrib, а затем включить contrib в основном файле makefile opencv. Для сборки opencv и contirb - следуйте официальной документации.

person Dmitrii Z.    schedule 23.07.2020