尝试从 OpenCV 使用 SURF 时出现 java.lang.UnsatisfiedLinkError

Posted

技术标签:

【中文标题】尝试从 OpenCV 使用 SURF 时出现 java.lang.UnsatisfiedLinkError【英文标题】:java.lang.UnsatisfiedLinkError when trying to use SURF from OpenCV 【发布时间】:2021-11-25 16:41:35 【问题描述】:

您好,我目前正在尝试使用 Java 中的 OpenCV 使用 FLANN 执行特征匹配。

这是本教程的代码: https://docs.opencv.org/master/d5/d6f/tutorial_feature_flann_matcher.html

我的项目是用“Java with Ant”创建的

我添加了以下依赖项

aistcv-4.5.3.jar、opencv-453.jar 和 opencv_java453.dll 到项目文件夹。

当我尝试运行此代码时,会出现错误消息。

run:
Exception in thread "main" java.lang.UnsatisfiedLinkError: org/opencv/xfeatures2d/SURF.create_0(DIIZZ)J
at org.opencv.xfeatures2d.SURF.create(SURF.java:92)
at surfflannmatchingdemo.SURFFLANNMatching.run(SURFFLANNMatchingDemo.java:43)
at surfflannmatchingdemo.SURFFLANNMatchingDemo.main(SURFFLANNMatchingDemo.java:80)
C:\Users\Juergen\AppData\Local\NetBeans\Cache\12.5\executor-snippets\run.xml:111: The following error occurred while executing this line:
C:\Users\Juergen\AppData\Local\NetBeans\Cache\12.5\executor-snippets\run.xml:68: Java returned: 1
BUILD FAILED (total time: 0 seconds)

我做错了什么?

【问题讨论】:

【参考方案1】:

SURF 仍然是专利。

只有从 src 构建且 OPENCV_ENABLE_NONFREE=ON 时才能使用它。

(如果是来自 SF 的预构建 jar 文件,您也可能没有任何 contrib 模块)

尝试用SIFT替换它

【讨论】:

我在线程“main”中遇到异常 java.lang.RuntimeException:无法编译的源代码 - 错误的符号类型:org.opencv.features2d.SIFT.create at surfflannmatchingdemo.SURFFLANNMatching.run(SURFFLANNMatchingDemo.java: 44)在surfflannmatchingdemo.SURFFLANNMatchingDemo.main(SURFFLANNMatchingDemo.java:81) C:\Users\Juergen\AppData\Local\NetBeans\Cache\12.5\executor-sn-ps\run.xml:111:执行时出现以下错误这一行:C:\Users\Juergen\AppData\Local\NetBeans\Cache\12.5\executor-sn-ps\run.xml:68:Java 返回:1 BUILD FAILED(总时间:2 秒) internal netbeans problem ? 我刚刚在 Eclipse 中尝试了这段代码。不幸的是还是同样的问题。 线程“main”java.lang.Error中的异常:未解决的编译问题:SIFT类型中的方法create(int,int,double,double,double)不适用于参数(double , int, int, boolean, boolean) at SURFFLANNMatching.run(SURFFLANNMatchingDemo.java:30) at SURFFLANNMatchingDemo.main(SURFFLANNMatchingDemo.java:67) 谢谢!我已替换为 SIFT 检测器 = SIFT.create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);【参考方案2】:

使用 FLANN 进行 OpenCV Java 特征匹配

如果有人和我有同样的问题,这里是解决方案。

import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.DMatch;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.Scalar;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.Features2d;

import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.xfeatures2d.SURF;

import org.opencv.features2d.SIFT;




class SURFFLANNMatching 
 public void run(String[] args) 
    String filename1 = args.length > 1 ? args[0] : "foto_111.png";
    String filename2 = args.length > 1 ? args[1] : "foto_222.png";
    Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.IMREAD_GRAYSCALE);
    Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.IMREAD_GRAYSCALE);
    if (img1.empty() || img2.empty()) 
        System.err.println("Cannot read images!");
        System.exit(0);
    
    
    
    
    //-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
    double contrastThreshold = 0.03; 
    double edgeThreshold = 2.0;
    double sigma = 1.0;
    int nOctaveLayers = 3; 
    int hessianThreshold = 400;
    boolean extended = false; 
    boolean upright = false;
            
// make error   SURF detector = SURF.create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);
    
// Solution start.
    SIFT detector = SIFT.create(hessianThreshold, nOctaveLayers, contrastThreshold, edgeThreshold, sigma);
// Solution stop.
    
    MatOfKeyPoint keypoints1 = new MatOfKeyPoint(), keypoints2 = new MatOfKeyPoint();
    Mat descriptors1 = new Mat(), descriptors2 = new Mat();
    
    detector.detectAndCompute(img1, new Mat(), keypoints1, descriptors1);
    detector.detectAndCompute(img2, new Mat(), keypoints2, descriptors2);
    
    //-- Step 2: Matching descriptor vectors with a FLANN based matcher
    // Since SURF is a floating-point descriptor NORM_L2 is used
    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
    List<MatOfDMatch> knnMatches = new ArrayList<>();
    matcher.knnMatch(descriptors1, descriptors2, knnMatches, 2);
    
    //-- Filter matches using the Lowe's ratio test
    float ratioThresh = 0.7f;
    List<DMatch> listOfGoodMatches = new ArrayList<>();
    for (int i = 0; i < knnMatches.size(); i++) 
        if (knnMatches.get(i).rows() > 1) 
            DMatch[] matches = knnMatches.get(i).toArray();
            if (matches[0].distance < ratioThresh * matches[1].distance) 
                listOfGoodMatches.add(matches[0]);
            
        
    
    MatOfDMatch goodMatches = new MatOfDMatch();
    goodMatches.fromList(listOfGoodMatches);
    //-- Draw matches
    Mat imgMatches = new Mat();
    Features2d.drawMatches(img1, keypoints1, img2, keypoints2, goodMatches, imgMatches, Scalar.all(-1),
            Scalar.all(-1), new MatOfByte(), Features2d.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS);
    //-- Show detected matches
    HighGui.imshow("Good Matches", imgMatches);
    HighGui.waitKey(0);
    System.exit(0);
 


public class SURFFLANNMatchingDemo 
  public static void main(String[] args) 
    // Load the native OpenCV library
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    new SURFFLANNMatching().run(args);
  

【讨论】:

即 62 行代码。哪些行是问题和解决方案最关键的行? 你好,这一行是解决方案 SIFTdetector = SIFT.create(hessianThreshold, nOctaveLayers, contrastThreshold, edgeThreshold, sigma);

以上是关于尝试从 OpenCV 使用 SURF 时出现 java.lang.UnsatisfiedLinkError的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenCV 从 android Camera2 将 YUV 转换为 RGB ImageReader 时出现问题,输出图像为灰度

OpenCV - 使用 SURF 描述符和 BruteForceMatcher 进行对象匹配

尝试在 opencv 4.5.1 中使用 SIFT 提取特征时出现问题

尝试导入 pybind opencv 模块时出现 libgtk 错误

尝试查找棋盘角时出现opencv python错误

OpenCV:使用 cvWriteFrame 从网络摄像头写入视频时出现内存泄漏