Opencv соответствует контурному изображению

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

У меня есть это изображение:

http://i55.tinypic.com/10fe1y8.jpg

И я хотел бы знать, как я могу рассчитать, какой из них лучше всего подходит для него:

http://i56.tinypic.com/zmxd13.jpg

(это должен быть тот, что справа)

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

Вот что я уже пробовал с помощью opencv:

Функция matchShapes — я попробовал эту функцию, используя 2 изображения в градациях серого, и я всегда получаю один и тот же результат на каждом сравнительном изображении, и значение кажется неправильным, так как оно равно 0,0002.

Итак, что я понял о matchShapes, но я не уверен, что это правильное предположение, так это то, что функция работает с парами контуров, а не с полными изображениями. Теперь это проблема, потому что, хотя у меня есть контуры изображений, которые я хочу сравнить, их сотни, и я не знаю, какие из них следует «спарить».

Поэтому я также попытался сравнить все контуры первого изображения с двумя другими с помощью итерации for, но я мог бы сравнить, например, контур 5 с контуром круга двух эталонов. изображения, а не 2 контура.

Также попробовал простую функцию cv::compare и matchTemplate, но ничего не получилось.


person out_sid3r    schedule 23.10.2011    source источник


Ответы (1)


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

Простые решения (с предположениями):

Для этих методов я предполагаю, что предоставленные вами изображения - это то, с чем вы работаете (т. Е. Объекты уже сегментированы и примерно одного масштаба. Кроме того, вам нужно будет исправить вращение (по крайней мере, грубо) , Вы можете сделать что-то вроде итеративного поворота изображения для сравнения каждые 10, 30, 60 или 90 градусов или любую другую грубость, которую, по вашему мнению, вам сойдет с рук.

Например,

for(degrees = 10; degrees < 360; degrees += 10)
    coinRot = rotate(compareCoin, degrees)
    // you could also try Cosine Similarity, or even matchedTemplate here.
    metric = SAD(coinRot, targetCoin) 
    if(metric > bestMetric)
        bestMetric = metric
        coinRotation = degrees

  • Сумма абсолютных разностей (SAD): это позволит вам быстро сравнить изображения после того, как вы определили примерный угол поворота.
  • Косинусное сходство: это работает немного по-другому, рассматривая изображение как одномерный вектор, а затем вычисляя многомерный угол между двумя векторами. Чем лучше совпадение, тем меньше будет угол.

Комплексные решения (возможно, более надежные):

Эти решения будут более сложными для реализации, но, вероятно, дадут более надежные классификации.


  • Расстояние Хаусдорфа: это ответ даст вам представление об использовании этого метода. Это решение, вероятно, также потребует коррекции вращения для правильной работы.
  • преобразование Фурье-Меллина: этот метод является расширением фазовой корреляции, который может извлекать преобразование поворота, масштабирования и перевода (RST) между двумя изображениями.
  • Обнаружение и извлечение признаков. /или инвариантность вращения) признаков на изображении и сравнение их с набором целевых признаков с помощью RANSAC, LMedS или простого метода наименьших квадратов. В OpenCV есть несколько примеров использования этой техники в matcher_simple.cpp. и matching_to_many_images.cpp. ПРИМЕЧАНИЕ. С помощью этого метода вы, вероятно, не захотите выполнять бинаризацию изображения, поэтому доступно больше обнаруживаемых функций.
person mevatron    schedule 24.10.2011
comment
Большое-большое спасибо за рекомендации... Я углублюсь в них... большое спасибо... Я дам немного отзывов, когда лучше проанализирую рекомендуемые шаги. - person out_sid3r; 24.10.2011