Сравнение двух изображений с OpenCV в Java
Я пытаюсь сравнить два изображения (определить, похожи они или нет) с использованием библиотеки OpenCV. Я настроил java-обертку и нашел несколько учебников (в основном на C/С++), которые я пытаюсь переписать на Java. Я использую метод обнаружения признаков.
Проблема заключается в том, что алгоритм, который у меня есть, не дает никаких разумных результатов (он утверждает, что два похожих изображения не имеют ничего общего и находит совпадения между другими двумя изображениями, которые совершенно разные). Может ли кто-нибудь предложить, как я должен использовать сокет openCV для получения некоторых разумных результатов?
Это мой код для сравнения изображений
private static void compareImages(String path1, String path2) {
System.out.println(path1 + "-" + path2);
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
// first image
Mat img1 = Imgcodecs.imread(path1, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
Mat descriptors1 = new Mat();
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
detector.detect(img1, keypoints1);
descriptor.compute(img1, keypoints1, descriptors1);
// second image
Mat img2 = Imgcodecs.imread(path2, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
Mat descriptors2 = new Mat();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
detector.detect(img2, keypoints2);
descriptor.compute(img2, keypoints2, descriptors2);
// match these two keypoints sets
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1, descriptors2, matches);
for (DMatch m : matches.toArray()) {
// how to use these values to detect the similarity? They seem to be way off
// all of these values are in range 50-80 which seems wrong to me
System.out.println(m.distance);
}
}
К сожалению, такие алгоритмы, как SURF и SIFT, недоступны в оболочке java, поэтому я использую ORB. У меня мало опыта работы с компьютерным зрением, я просто пытаюсь заставить этот простой алгоритм сравнения работать, чтобы добиться разумного результата. Я был бы рад за любую помощь!
EDIT: мой прецедент использует этот алгоритм для изображений, снятых под разными углами. Я обновил свой код, чтобы лучше форматировать.
Пример сравнения изображений:
![введите описание изображения здесь]()
Ответы
Ответ 1
Только мои два цента:
-
Доступ к SURF и SIFT в java: openCV DescriptorExtractor Reference. Я попробовал реализацию FREAK три года назад и выяснил, что некоторые изменения происходят с двоичным дескриптором, когда openCV передает их на Java. Возможно, ORB подвержен той же самой проблеме. Вы сравнивали данные дескрипторов с c или С++ с теми, что на стороне java?
-
Сопряжение грубой силы находит наилучшую функцию соответствия изображения поезда для КАЖДОЙ функции в изображении запроса. Даже если это выглядит совершенно иначе. Вы должны просеивать спички и бросать плохие. Существует несколько стратегий, простой - просто взять лучшие 20% матчей (но это не снизит ALL outlier). Progressive Sample Consensus очень хорошо работает в моей настройке.
- Использование возможностей для сравнения подобия изображения имеет это подводные камни. Количество функций и качество варьируются в зависимости от размера и содержимого изображения, что затрудняет сравнение изображений во всем мире (в случае, если вы хотите узнать, какое из двух изображений больше похоже на ссылку, чем на другую). Вы можете оценить преобразование с одного изображения на другое с помощью
Calib3d.findHomography(obj, scene, CV_RANSAC);
и использовать нормализованную разность пикселей перекрывающихся областей.
Ответ 2
Как указано в this SO Question, самым простым и простым способом является сравнение гистограмм. Если ваш алгоритм должен работать только для определенного набора данных, попробуйте использовать разные цветовые каналы, чтобы увидеть, где изображения в вашем наборе имеют наибольшее сходство.
Гистограммный подход может показаться непрактичным, но с учетом сходства цвета с вашими изображениями я считаю, что это может быть полезно.
После сравнения гистограмм двух изображений в Photoshop:
![сравнение гистограмм]()