@gibsonen

ORB дескрипторы как найти похожие изображения?

Имеются 2 изображения, нахожу для каждого их дескрипторы ORB. Далее отфильтровываю дескрипторы по расстоянию и по алгоритму RANSAC , но выходит не то что надо ухо указывает на логотип и т д . В чем проблема?

5cd4208bd6727803030207.jpeg

Ниже код:
public static void compareFeature(String filename1, String filename2) {
        ORB orb = ORB.create();

        DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

        Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
        Mat descriptors1 = new Mat();
        MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
        orb.detectAndCompute(img1, new Mat(), keypoints1, descriptors1);

// second image
        Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
        Mat descriptors2 = new Mat();
        MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
        orb.detectAndCompute(img2, new Mat(), keypoints2, descriptors2);


// MATCHING
// match these two keypoints sets
        MatOfDMatch matches = new MatOfDMatch();
        matcher.match(descriptors1, descriptors2, matches);

        List<DMatch> matchesList = matches.toList();
        // ratio test
        LinkedList<DMatch> good_matches = new LinkedList<>();
        Double max_dist = 0.0;
        Double min_dist = 100.0;
        for (DMatch aMatchesList1 : matchesList) {
            Double dist = (double) aMatchesList1.distance;
            if (dist < min_dist)
                min_dist = dist;
            if (dist > max_dist)
                max_dist = dist;
        }
        for (DMatch aMatchesList : matchesList) {
            if (aMatchesList.distance <= (1.5 * min_dist))
                good_matches.addLast(aMatchesList);
        }
        // get keypoint coordinates of good matches to find homography and remove outliers using ransac
        List<Point> pts1 = new ArrayList<>();
        List<Point> pts2 = new ArrayList<>();
        for (DMatch good_matche : good_matches) {
            pts1.add(keypoints1.toList().get(good_matche.queryIdx).pt);
            pts2.add(keypoints2.toList().get(good_matche.trainIdx).pt);
        }

        // convertion of data types - there is maybe a more beautiful way
        Mat outputMask = new Mat();
        MatOfPoint2f pts1Mat = new MatOfPoint2f();
        pts1Mat.fromList(pts1);
        MatOfPoint2f pts2Mat = new MatOfPoint2f();
        pts2Mat.fromList(pts2);

        // Find homography - here just used to perform match filtering with RANSAC, but could be used to e.g. stitch images
        // the smaller the allowed reprojection error (here 15), the more matches are filtered
        System.out.println("pts1mat " + pts1Mat.size());
        System.out.println("pts2mat " + pts2Mat.size());
        Mat Homog = Calib3d.findHomography(pts1Mat, pts2Mat, Calib3d.RANSAC, 15, outputMask, 2000, 0.995);
        System.out.println("pts1mat " + pts1Mat.size());
        System.out.println("pts2mat " + pts2Mat.size());
        // outputMask contains zeros and ones indicating which matches are filtered
        LinkedList<DMatch> better_matches = new LinkedList<DMatch>();
        for (int i = 0; i < good_matches.size(); i++) {
            if (outputMask.get(i, 0)[0] != 0.0) {
                better_matches.add(good_matches.get(i));
            }
        }
        // DRAWING OUTPUT
        Mat outputImg = new Mat();
        // this will draw all matches, works fine
        MatOfDMatch better_matches_mat = new MatOfDMatch();
        better_matches_mat.fromList(better_matches);
        Features2d.drawMatches(img1, keypoints1, img2, keypoints2, better_matches_mat, outputImg);
        // save image
        Imgcodecs.imwrite("result.jpg", outputImg);
        System.out.println("better_matches_mat " + better_matches_mat.size());
    }
  • Вопрос задан
  • 237 просмотров
Пригласить эксперта
Ответы на вопрос 1
@forspamonly2
что оно на этом этапе должно сделать - отобрать похожие признаки, расположенные на картинках примерно одинаково друг относительно друга. для этого оно пытается подобрать такую матрицу проекции одной картинки на другую, чтобы совпало максимальное количество похожих признаков (с целью отбросить несовпавшие). и делается это исходя из предположения, что такая проекция существует.

есть случаи, когда это работает: например стереопары картинок, соседние кадры из видео или сильно перекрывающиеся изображения при фотограмметрии - оно сможет вычислить наложение и всё будет хорошо.

есть случаи, когда это не работает совсем: на картинках с повторяющимися текстурами, или например, если на одной картинке объект из второй встречается несколько раз в разных местах и позах - оно будет пытаться примостить картинку с единичным объектом так, чтобы на нём в нужные места попали лучше всего совпавшие части от разных объектов.

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

что с этим можно делать - зависит от того, что вам нужно.

скажем, если вы пытаетесь искать конкретно логотипы на футболках, то имеет смысл насобирать небольшой визуальный словарь фич, которые в них встречаются, и перед тем, как пытаться устанавливать соответствия, отфильтровать из всех фич картинок только те, которые встрачаются в логотипах. чтобы было побольше фич от логотипов и поменьше фич от пальцев-ушей.

ещё можно попробовать переписать подбор матрицы так, чтобы он не рассматривал вырожденные варианты. я этим занимался давно (в 11-12 годах), orb дескрипторов тогда ещё не было (у меня были surf-sift), но вот этот подбор гомографии рансаком мне нормальных результатов никогда не выдавал - оно постоянно пыталось вывернуть картинку наизнанку (матчить внутренние углы вместо внешних). помнится, я пытался подпереть костылём чтобы оно не ставило отрицательные коэффициенты в матрицы, но там всё сложно сделано было (кажется, оно несколько алгоритмов поддерживает кроме рансака и логика размазана по слоям как попало). в общем, так и не доделал - до того, как это заработало, я для своей конкретной задачи придумал упрощённый способ верификации взаиморасположения признаков без этих матриц. да и по производительности мне рансаковский перебор проекций не подходил.

поэтому, последнее предложение: попробуйте обойтись без этой гомографии. хотя, для ваших картинок, по-моему, основные простые варианты не подойдут.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы