【问题标题】:Performance Issues in OpenCV for Android Keypoint Matching and threshold using ORB and RANSAC使用 ORB 和 RANSAC 进行 Android 关键点匹配和阈值的 OpenCV 中的性能问题
【发布时间】:2016-09-26 23:12:17
【问题描述】:

我最近开始在 Android Studio 上开发一个应用程序,我刚刚完成了代码的编写。我得到的准确度非常令人满意,但设备花费的时间是 很多。 {}我遵循了一些关于如何在 android studio 上监控性能的教程,发现一小部分我的代码花费了 6 秒一半我的应用显示整个结果所需的时间。我在 OpenCV/JavaCV 上看到了很多帖子 Java OpenCV - extracting good matches from knnMatchOpenCV filtering ORB matches,但没有遇到任何人提出这个问题。 OpenCV 链接http://docs.opencv.org/2.4/doc/tutorials/features2d/feature_homography/feature_homography.html 确实提供了一个很好的教程,但与 C++ 相比,OpenCV 中的 RANSAC 函数对关键点采用不同的参数。

这是我的代码

     public Mat ORB_detection (Mat Scene_image, Mat Object_image){
    /*This function is used to find the reference card in the captured image with the help of
    * the reference card saved in the application
    * Inputs - Captured image (Scene_image), Reference Image (Object_image)*/
    FeatureDetector orb = FeatureDetector.create(FeatureDetector.DYNAMIC_ORB);
    /*1.a Keypoint Detection for Scene Image*/
    //convert input to grayscale
    channels = new ArrayList<Mat>(3);
    Core.split(Scene_image, channels);
    Scene_image = channels.get(0);
    //Sharpen the image
    Scene_image = unsharpMask(Scene_image);
    MatOfKeyPoint keypoint_scene = new MatOfKeyPoint();
    //Convert image to eight bit, unsigned char
    Scene_image.convertTo(Scene_image, CvType.CV_8UC1);
    orb.detect(Scene_image, keypoint_scene);
    channels.clear();

    /*1.b Keypoint Detection for Object image*/
    //convert input to grayscale
    Core.split(Object_image,channels);
    Object_image = channels.get(0);
    channels.clear();
    MatOfKeyPoint keypoint_object = new MatOfKeyPoint();
    Object_image.convertTo(Object_image, CvType.CV_8UC1);
    orb.detect(Object_image, keypoint_object);

    //2. Calculate the descriptors/feature vectors
    //Initialize orb descriptor extractor
    DescriptorExtractor orb_descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
    Mat Obj_descriptor = new Mat();
    Mat Scene_descriptor = new Mat();
    orb_descriptor.compute(Object_image, keypoint_object, Obj_descriptor);
    orb_descriptor.compute(Scene_image, keypoint_scene, Scene_descriptor);

    //3. Matching the descriptors using Brute-Force
    DescriptorMatcher brt_frc = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
    MatOfDMatch matches = new MatOfDMatch();
    brt_frc.match(Obj_descriptor, Scene_descriptor, matches);

    //4. Calculating the max and min distance between Keypoints
    float max_dist = 0,min_dist = 100,dist =0;
    DMatch[] for_calculating;
    for_calculating = matches.toArray();
    for( int i = 0; i < Obj_descriptor.rows(); i++ )
    {   dist = for_calculating[i].distance;
        if( dist < min_dist ) min_dist = dist;
        if( dist > max_dist ) max_dist = dist;
    }

    System.out.print("\nInterval min_dist: " + min_dist + ", max_dist:" + max_dist);
    //-- Use only "good" matches (i.e. whose distance is less than 2.5*min_dist)
    LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
    double ratio_dist=2.5;
    ratio_dist = ratio_dist*min_dist;
    int i, iter = matches.toArray().length;
    matches.release();

    for(i = 0;i < iter; i++){
        if (for_calculating[i].distance <=ratio_dist)
            good_matches.addLast(for_calculating[i]);
    }
    System.out.print("\n done Good Matches");

    /*Necessary type conversion for drawing matches
    MatOfDMatch goodMatches = new MatOfDMatch();
    goodMatches.fromList(good_matches);
    Mat matches_scn_obj = new Mat();
    Features2d.drawKeypoints(Object_image, keypoint_object, new Mat(Object_image.rows(), keypoint_object.cols(), keypoint_object.type()), new Scalar(0.0D, 0.0D, 255.0D), 4);
    Features2d.drawKeypoints(Scene_image, keypoint_scene, new Mat(Scene_image.rows(), Scene_image.cols(), Scene_image.type()), new Scalar(0.0D, 0.0D, 255.0D), 4);
    Features2d.drawMatches(Object_image, keypoint_object, Scene_image, keypoint_scene, goodMatches, matches_scn_obj);
    SaveImage(matches_scn_obj,"drawing_good_matches.jpg");
    */

    if(good_matches.size() <= 6){
        ph_value = "7";
        System.out.println("Wrong Detection");
        return Scene_image;
    }
    else{
        //5. RANSAC thresholding for finding the optimum homography
        Mat outputImg = new Mat();
        LinkedList<Point> objList = new LinkedList<Point>();
        LinkedList<Point> sceneList = new LinkedList<Point>();

        List<org.opencv.core.KeyPoint> keypoints_objectList = keypoint_object.toList();
        List<org.opencv.core.KeyPoint> keypoints_sceneList = keypoint_scene.toList();

        //getting the object and scene points from good matches
        for(i = 0; i<good_matches.size(); i++){
            objList.addLast(keypoints_objectList.get(good_matches.get(i).queryIdx).pt);
            sceneList.addLast(keypoints_sceneList.get(good_matches.get(i).trainIdx).pt);
        }
        good_matches.clear();
        MatOfPoint2f obj = new MatOfPoint2f();
        obj.fromList(objList);
        objList.clear();

        MatOfPoint2f scene = new MatOfPoint2f();
        scene.fromList(sceneList);
        sceneList.clear();

        float RANSAC_dist=(float)2.0;
        Mat hg = Calib3d.findHomography(obj, scene, Calib3d.RANSAC, RANSAC_dist);

        for(i = 0;i<hg.cols();i++) {
            String tmp = "";
            for ( int j = 0; j < hg.rows(); j++) {

                Point val = new Point(hg.get(j, i));
                tmp= tmp + val.x + " ";
            }
        }

        Mat scene_image_transformed_color = new Mat();
        Imgproc.warpPerspective(original_image, scene_image_transformed_color, hg, Object_image.size(), Imgproc.WARP_INVERSE_MAP);
        processing(scene_image_transformed_color, template_match);

        return outputImg;
    }
} }

这部分是在运行时需要 6 秒来实现的 -

    LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
    double ratio_dist=2.5;
    ratio_dist = ratio_dist*min_dist;
    int i, iter = matches.toArray().length;
    matches.release();

    for(i = 0;i < iter; i++){
        if (for_calculating[i].distance <=ratio_dist)
            good_matches.addLast(for_calculating[i]);
    }
    System.out.print("\n done Good Matches");}

我在想也许我可以使用 NDK 用 C++ 编写这部分代码,但我只是想确定问题是语言而不是代码本身。 请不要严格,第一个问题!非常感谢任何批评!

【问题讨论】:

  • 暴力匹配是O(n^2),所以要么使用更快的匹配方法(FLANN),要么减少关键点的数量。但是特征提取本身可能非常昂贵。我怀疑切换到 C++ 是否会给 opencv 函数带来好处(可能它们会启动一些 C 二进制文件?),但我从未尝试过......
  • 您在图像上提取了多少个关键点?
  • 我会说它更有可能是检测部分的图像分辨率。 OpenCV 中 ORB 的默认特征数是 500,我在 2012 年在 Nexus 4 上进行了 1ms 的蛮力匹配,用于实时跟踪。
  • @micka 我提取了 500 个关键点,但并不是说我可以在 Java 中更改它。但蛮力似乎并没有像所说的那样减缓这个过程。我在上面显示的匹配过滤是减慢速度的原因。内存消耗突然爆发。如果你愿意,我可以添加更多细节。我将用 C++ 编写所有内容以防万一,并报告
  • 问题在于分辨率的大小。如果我降低分辨率,那么代码很快,但检测不是最好的。

标签: android opencv image-processing


【解决方案1】:

所以问题是 logcat 给了我错误的计时结果。滞后是由于后来代码中出现了巨大的高斯模糊。我没有使用System.out.print,而是使用了System.currentTimeMillis,这向我展示了错误。

【讨论】:

  • 您能详细解释一下吗?我很感兴趣。
  • @Gewure 在我的情况下,高斯模糊需要很长时间才能实现 w.r.t.我的代码的另一部分。
  • 我仍然不完全理解 ;_) 你有一个高斯模糊过滤器..它与你的代码的其他部分有什么关系?你是多次调用它,还是花了这么长时间?
  • 模糊本身​​需要很长时间。其余代码按预期运行。问题是在实现这个之后,我没想到高斯模糊会以任何方式变慢,所以我完全忽略了它。
  • @Gewure 很高兴我能提供帮助。你也遇到过类似的事情吗?
猜你喜欢
  • 2020-09-28
  • 2013-04-06
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多