Python, SURF (ускоренная надежная функция) в OpenCV

задняя часть

Python, SURF (ускоренная надежная функция) в OpenCV

В предыдущем блоге был представлен SIFT для обнаружения и описания ключевых точек, но он относительно медленный., в этом блоге будет представлена ​​его оптимизированная версия — SURF (Speeded-Up Robust Features), которая является ускоренной версией SIFT;

  • В SIFT Лоу использует разность гауссиана, чтобы аппроксимировать лапласиан гауссиана, чтобы найти масштабное пространство.
  • С помощью интегрального изображения SURF может легко вычислить свертку блочного фильтра. Параллельно вычисляйте разные масштабы. Кроме того, SURF также зависит от детерминанта матрицы Гессе масштаба и местоположения.
  • SURF добавляет множество функций для увеличения скорости каждого шага. Это в 3 раза быстрее, чем SIFT, а производительность сравнима с SIFT.
  • SURF хорошо справляется с размытыми и повернутыми изображениями, но не так хорошо справляется с изменением точки обзора и изменения освещения.

1. Рендеринг

Визуализация параметров SURF по умолчанию выглядит следующим образом:

Проверено много ключевых моментов, и исходное изображение закрыто.在这里插入图片描述 SURF скорректировал порог и нашел около 50 ключевых точек.Визуализация выглядит следующим образом: 在这里插入图片描述 Использование U-SURF не вычисляет направление, все направления одно, рендеринг ключевых точек SURF выглядит следующим образом: 在这里插入图片描述 Эффект вычисления по умолчанию составляет 64D, как указано выше, скорректированный до 128D, а эффект U-SURF выглядит следующим образом: в основном нет разницы 在这里插入图片描述

2. Принцип

OpenCV использует SURF.detect(), SURF.compute() и т. д. для поиска ключевых точек и дескрипторов.

2.1 Почему SURF быстрее, чем SIFT?

  • Вейвлет-отклик можно легко найти, используя интегральное изображение в любом масштабе.
  • Вращение не деформируется, поэтому отсутствие необходимости искать ориентацию ускорит процесс.
  • SURF предоставляет функцию, называемую Upright-SURF или U-SURF. Он увеличивает скорость и очень надежен в диапазоне +-15°.
  • OpenCV поддерживает Upright-SURF, U-SURF, в зависимости от флагов. Если 0, вычисляется направление. Если 1, направление не рассчитывается и скорость больше.
  • Чем ниже размерность, тем быстрее вычисление и сопоставление, но тем выше значимость признаков. OpenCV поддерживает оба варианта, устанавливая значения флага, расширенные до 0 и 1 для 64 тусклых и 128 тусклых соответственно (по умолчанию 128 тусклых)
  • Еще одним важным улучшением является использование нотации Лапласа (траектории матрицы Гессе) для потенциальных точек интереса. Это не увеличивает вычислительные затраты. Символ Лапласа отличает яркие пятна на темном фоне от противоположного.
  • На этапе сопоставления сравниваются только объекты с одинаковым контрастом (как показано на рисунке ниже). Эта минимальная информация обеспечивает более быстрое сопоставление без ухудшения производительности дескриптора.

2.3 Как получить SIFT и SURF?

SIFT и SURF — это запатентованные алгоритмы, которые были удалены в OpenCV3.0 и более поздних версиях. Перенесено на версию opencv-contrib-python. Итак, есть следующие способы его получения: 1) Установите версии ниже opencv3 2) Удалите opencv3 или выше, а opencv-contrib-python установит указанную версию 3) Установите opencv3 или выше, установите opencv-contrib-python, скомпилируйте и установите opencv из исходного кода;

Таким образом, метод 2 более удобен и осуществим и требует всего два шага:

  1. удалить opencv-python
  2. Установить указанную версию opencv-contrib-python==3.4.2.17
pip uninstall opencv-python

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.2.17

Вы можете видеть успех 在这里插入图片描述

3. Исходный код

# 寻找SURF关键点和描述符并绘制
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('images/butterfly.jpg', 0)

# 创建SURF对象,可以在创建时指定参数也可以稍后设置参数
# 此处设置 Hessian阈值为 400
sift = cv2.xfeatures2d.SIFT_create()
print('sift: ', sift)
surf = cv2.xfeatures2d.SURF_create()
print('surf: ', surf,
      ' \ndefaultParameter\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

# 寻找SURF关键点和描述符
# kp:返回的关键点列表,des:numpy数组
kp, des = surf.detectAndCompute(img, None)
# 绘制关键点在图片上
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)
plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('more keypoints'), plt.show()

print('keypoints: ', len(kp))

# 检查当前Hessian阈值
# print(surf.getHessianThreshold())

# 调整Hessian阈值,此处设置为50000,但一般最佳设置为300~500
surf.setHessianThreshold(50000)
print(' parameters\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

# 再一次计算关键点和描述符
kp, des = surf.detectAndCompute(img, None)

print('keypoints: ', len(kp))

# 绘制关键点在图片上
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('less than 50 keypoints'), plt.show()

# U-SURF不会计算方向
# print(surf.getUpright())
surf.setUpright(True)
print(' parameters\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

# 重新计算关键点和描述符,并绘制
kp = surf.detect(img, None)
print('keypoints: ', len(kp))
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('U-SURF'), plt.show()

# 所有方向显示在同一方向,它比以前快多了。如果您正在处理方向不成问题的情况(如全景缝合)等,使用U-SURF会更好。
# 寻找描述符的大小
# print(surf.descriptorSize())
# extended为false,默认为64D
# print(surf.getExtended())

# 设置描述符为128D
surf.setExtended(True)
print(' parameters\thessianThreshold: ', surf.getHessianThreshold(),
      ' upright: ', surf.getUpright(),
      ' extended: ', surf.getExtended(),
      ' descriptors: ',surf.descriptorSize())

kp, des = surf.detectAndCompute(img, None)
print('keypoints: ',len(kp))
img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)

plt.imshow(img2), plt.xticks([]), plt.yticks([]), plt.title('128D res'), plt.show()

Ссылаться на