特征点检测的实现,初学者对各种特征点检测算法搞得晕头转向,网上看到的文章实现和解释比较零碎,在此特意将各种算法实现整理,同样不讲原理,只写实现。当一回彻底的代码搬运工,整理实现各种经典特征点检测算法,共计6种,同时将效果显示在一幅画面中。(由此下一篇应该总结下各种特征匹配算法)

代码参考:


代码及评论参考:


harris是最早提出的特征提取算法:

sift:harris Corner算法能够解决旋转不变性问题,但不能解决尺度变化问题,由此背景提出了sift算法
surf:sift的计算效果较好,但是计算速度较慢, surf(speed up robust features)速度是sift算法的3倍。

fast:是特征检测的再提速(能够满足实时检测关键点的要求)

breif:是特征描述子计算的简化与提速,sift与surf算法每个关键的特征描述子是128维都是单精度,所以每个描述子占128*4=512bytes的内存,breif每个特征描述子32bytes,大大减少内存,且运算快(利于嵌入式开发)

orb:算法结合了fast算法与brief算法优点,是目前最快的目标检测算法:

opencv开运算源码 opencv经典算法_opencv

# 各种特征点检测sift,surf,Shi-Tomasi,Fast检测算法,BRIEF算法,ORB检测算法
# 注:sift必须在3.4.2+下运行,后面的有专利
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 10

# 获取图像部分
img = cv2.imread('image/small.jpg', 1)
exx = 0.45  # 不改变尺寸可能匹配不到
img = cv2.resize(img, dsize=None, fx=exx, fy=exx)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Harris角点检测
img_harris = img.copy()
gray = np.float32(gray)
# 图像转换为float32
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# result is dilated for marking the corners, not important
dst = cv2.dilate(dst, None)  # 图像膨胀
# Threshold for an optimal value, it may vary depending on the image.
# img[dst>0.00000001*dst.max()]=[0,0,255] #可以试试这个参数,角点被标记的多余了一些
img_harris[dst > 0.01 * dst.max()] = [0, 0, 255]  # 角点位置用红色标记
# cv2.imshow('im',img_harris)
print(dst > 0.01 * dst.max())
# 这里的打分值以大于0.01×dst中最大值为边界

# 使用SIFT检测特征点
sift = cv2.xfeatures2d.SIFT_create()
# 获取关键点和描述符
kp1, des1 = sift.detectAndCompute(img, None)
# 在图中显示特征点
img_small_sift = img.copy()
img_small_sift = cv2.drawKeypoints(img_small_sift, kp1, outImage=np.array([]),
                                   flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# 使用SURF检测特征点
surf = cv2.xfeatures2d.SURF_create(400)
# 找到关键点和描述符
key_query, desc_query = surf.detectAndCompute(img, None)
# 把特征点标记到图片上
img_small_surf = img.copy()
img_small_surf = cv2.drawKeypoints(img_small_surf, key_query, img_small_surf)

# Shi-Tomasi 角点检测
img_shi = img.copy()
corners = cv2.goodFeaturesToTrack(gray, 72, 0.01, 10)  # 棋盘上的所有点
corners = np.int0(corners)
for i in corners:
    x, y = i.ravel()  # 多维数组降为1维,但是用ravel后修改会影响原数组,flatten
    cv2.circle(img_shi, (x, y), 10, (0, 255, 255), -1)  # 在原图像上画出角点位置

# Fast算法检测特征点
# 角点检测,只有关键点,没有描述符

img_fast = img.copy()
fast = cv2.FastFeatureDetector_create(threshold=20, nonmaxSuppression=True,
                                      type=cv2.FAST_FEATURE_DETECTOR_TYPE_9_16)  # 获取FAST角点探测器
kp = fast.detect(img_fast, None)  # 描述符
img_fast = cv2.drawKeypoints(img_fast, kp, img_fast, color=(255, 0, 0))  # 画到img上面

print("Threshold: ", fast.getThreshold())  # 输出阈值
print("nonmaxSuppression: ", fast.getNonmaxSuppression())  # 是否使用非极大值抑制
print("Total Keypoints with nonmaxSuppression: ", len(kp))  # 特征点个数

# # BRIEF算法
# 初始化STAR检测器
img_brief = img.copy()
star = cv2.xfeatures2d.StarDetector_create()
# 初始化BRIEF特征提取器
brief = cv2.xfeatures2d.BriefDescriptorExtractor_create()
# 使用STAR寻找特征点
kp = star.detect(img_brief, None)
# 计算特征描述符
kp, des = brief.compute(img_brief, kp)
img_brief = cv2.drawKeypoints(img_brief, kp, img_brief, color=(255, 0, 0))

# ORB检测算法
img_orb = img.copy()
orb = cv2.ORB_create()
kp = orb.detect(img_orb, None)
kp, des = orb.compute(img_orb, kp)
img_orb = cv2.drawKeypoints(img_orb, kp, img_orb, color=(0, 255, 0), flags=0)

# 写文字
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'origin', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img_harris, 'img_harris', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img_small_sift, 'img_small_sift', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img_small_surf, 'img_small_surf', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img_fast, 'img_fast', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img_brief, 'img_brief', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img_orb, 'img_orb', (10, 30), font, 1, (255, 255, 0), 2, cv2.LINE_AA)


res1 = np.hstack((img, img_harris, img_small_sift, img_small_surf))
res2 = np.hstack((img, img_fast, img_brief, img_orb))

res = np.vstack((res1, res2))
cv2.imshow('res', res)
# cv2.resizeWindow("res", 640, 480);
cv2.waitKey()