Error : java.lang.UnsatisfiedLinkError with Charuco Camera Calibration (DetectorParameters)

Error : java.lang.UnsatisfiedLinkError with Charuco Camera Calibration (DetectorParameters)

大家早上好。我目前正在从事一个项目,在该项目中,我必须高精度地检测图像中的对象坐标。我曾尝试使用普通棋盘进行相机校准,但重投影误差太高,所以我决定使用 Charuco 校准模式。我正在使用 OpenCv 3.4 和 Java(项目约束)。由于 Java 的 OpenCv 中未包含 Aruco 函数,因此我在我的项目中创建了一个新包,其中包含必要的 类。您可以在以下 link 中找到 Aruco 代码: Aruco Code 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 包,但我不知道如何在项目的构建路径中包含一个包。

我们非常欢迎任何形式的帮助!谢谢 ! :)

该错误表明您的 opencv 包没有您正在使用的特殊模块;

为了解决这个问题,您需要找到一个带有您需要的模块的预构建 opencv(在您的确切情况下,它被涂在 contrib 库中,因此 this 可能会有所帮助。

如果您想从源代码构建它 - 您应该在 cmake 属性中启用所需的模块。对于 contrib - 您需要先 cmake contrib 项目,然后在主 opencv makefile 中启用 contrib。对于构建 opencv 和 contirb - 请遵循官方文档。