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 более удобен и осуществим и требует всего два шага:
- удалить opencv-python
- Установить указанную версию 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()