角點特征常常是圖像中獨特的存在,比如你在玩拼圖游戲時,首先肯定會去找一些獨一無二的匹配項,比如人像的眼睛,嘴巴,這些特征你很容易判斷哪些碎片應該拼湊在一起,而相比之下,那些比較常見的特征你需要最后多次調(diào)整才能找到對的位置。角點特征就是這樣較獨特的存在,下圖中矩形的右上角點區(qū)域,無論你往哪個方向移動,圖像的信息都會發(fā)生變化,而邊緣則沿某一個方向移動時不會變化,至于矩形內(nèi)部區(qū)域,則無論哪個方向移動,圖像信息沒有變化[引用自官方教程]。

本文內(nèi)容涉及以下內(nèi)容(參考OpenCV3 計算機視覺第6章)
- Harris角點檢測
- Shi-Tomasi角點檢測(Harris的修改版)
- FAST角點檢測
有了特征點,怎么用呢?你可以比對不同圖像的特征信息,進行目標檢測、圖像拼接等。在OpenCV中,可以通過下面的算子來進行特征匹配:
- Brute-Force匹配法,也稱暴力匹配法
- 基于FLANN的匹配法
1.使用Harris以及Shi-Tomasi算子獲取角點
Harris | Shi-Tomasi角點

注:這里采用Shi-Tomasi僅保留最好的12個角點信息(匹配比較好),而harris輸出了全部角點,圓圈顏色深表示該處檢測到的次數(shù)多。
import cv2
import numpy as np
import time
img = cv2.imread('approx_star.png', -1)
img_copy = img.copy()
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gaussian_img = cv2.GaussianBlur(gray_img,(3, 3),0)
# 輸入圖像必須是float32
float_img = np.float32(gaussian_img)
# Harris角點檢測
## src: 輸入圖像
## blockSize:鄰域大小
## ksize:Sobel算子中的核大小
## k :Harris檢測參數(shù),經(jīng)驗范圍:[0.04, 0.06],值越大,假角點越少,不過可能會漏檢
start_time = time.time()
dst = cv2.cornerHarris(float_img, 4, 3, 0.08)
end_time = time.time()
print('Harris Detection used :%s ms.' % ((end_time - start_time) * 1000))
dot_locs = np.where(dst > (0.01 * dst.max()))
for loc in zip(*dot_locs[::-1]):
cv2.circle(img, loc, 5, (25, 25, 255), 1)
# Shi-Tomasi方法檢測
## src: 輸入圖像
## maxCorners:輸出的角點數(shù)目,可以幫助你找到最佳的maxCorners個角點,會將角點進行排序
## qualityLevel:檢測質(zhì)量水平系數(shù),經(jīng)驗值[0.01, 0.1]
## minDistance:最小的角點距離,小于該距離的角點會被忽視
start_time = time.time()
corners = cv2.goodFeaturesToTrack(gaussian_img, 12, 0.01, 10)
end_time = time.time()
print('goodFeaturesToTrack Detection used :%s ms.' % ((end_time - start_time) * 1000))
corners = np.int64(corners)
for corner in corners:
x, y = corner.flatten()
cv2.circle(img_copy, (x, y), 5, (255, 25, 255), 3)
cv2.imshow('harris_corners', img)
cv2.imshow('shi-tomasi_corners', img_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 耗時情況:
# Harris Detection used :5.984783172607422 ms.
# goodFeaturesToTrack Detection used :9.972572326660156 ms.
補充:
1.關(guān)于參數(shù)ksize和檢測自由設置參數(shù)k,可參考博客【cornerHarris中的ksize和k是什么意思】--https://www.jb51.cc/python/533133.html
2.官方角點檢測參考鏈接:https://docs.opencv.org/3.0-beta/modules/imgproc/doc/feature_detection.html?highlight=cv2.cornerharris#cv2.cornerHarris
3.goodFeaturesToTrack 函數(shù)參數(shù)詳解https://blog.csdn.net/guduruyu/article/details/69537083 這個函數(shù)可以輸入mask信息
4.對于有更精細檢測需求的,可以使用cornerSubPix()來檢測亞像素角點
對于FAST檢測角點的基本使用方法如下:
# 創(chuàng)建檢測器,大多數(shù)情況下閾值設置較大,太低會造成大量的假特征點
# 選擇非極大值抑制會使得特征點會少一些,避免一些假特征點
# type可選擇FAST_FEATURE_DETECTOR_TYPE_9_16,在像素周圍取16個點,當9個滿足條件,就是特征點,除此之外,可選擇7_12, 5_8
fast=cv2.FastFeatureDetector_create(threshold = 20, nonmaxSuppression=False,
type=cv2.FAST_FEATURE_DETECTOR_TYPE_9_16)
# 返回的kp為keypoint類,你可以使用kp[0].pt獲取第一個特征點的坐標信息
# detect第二個參數(shù)為特征點,第三個參數(shù)為mask
kp = fast.detect(gray_img, None)
# 耗時情況
# FAST Detection used :0.9963512420654297 ms.??
參考博客:
1.OPENCV圖像特征點檢測與FAST算法https://www.cnblogs.com/dengxiaojun/p/5302778.html講解該函數(shù)的算法及參數(shù)
2.KeyPoint類參考博客:https://blog.csdn.net/leonardohaig/article/details/81289648
2.特征點匹配
你可以用特征點用在兩幅圖的信息比對上,這一點在圖像拼接中尤為重要,至于說用特征進行目標檢測,比如《OpenCV3 計算機視覺》中有將特征信息作為紋身信息的比對.不過,當你的環(huán)境特征信息量比較多(比如風景)的時候,匹配出錯的概率非常大.
# ORB特征點匹配
import cv2
import numpy as np
import time
# 特征圖像
img = cv2.imread('fuji_features1.png',-1)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 待匹配圖像
img1 = cv2.imread('fuji_feature.jpg',-1)
gray_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
start_time = time.time()
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(gray_img, None)
kp2, des2 = orb.detectAndCompute(gray_img1, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)
matches = bf.match(des1, des2)
end_time = time.time()
print('ORB Detect Features and BFMatch used :%s ms.' % ((end_time - start_time) * 1000))
# good_matches = []
# for m, n in matches:
# if m.distance < 0.75 * n.distance:
# good_matches.append([m])
# 按照特征點距離進行排序,距離越小約好
# 參考博客:https://blog.csdn.net/u013000248/article/details/85325136
matches = sorted(matches, key = lambda x : x.distance)
img2 = cv2.drawMatches(img, kp1, img1, kp2, matches[:40], np.array([]), flags = 2)
cv2.imshow('ORB_corners', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.1 ORB 特征 + FLANN匹配
需要注意一下,ORB 進行特征提取的descriptor格式需要轉(zhuǎn)換下,否則是無法進行FLANN匹配
FLANN_INDEX_KDTREE = 1
indexParams = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
searchParams = dict(check = 50)
flann = cv2.FlannBasedMatcher(indexParams, searchParams)
# 轉(zhuǎn)為np.float32
matches = flann.knnMatch(np.float32(des1), np.float32(des2), k = 2)
相關(guān)博客:
角點特征檢測之三(FLANN匹配)https://blog.csdn.net/wsp_1138886114/article/details/90578810
關(guān)于opencv-python的特征檢測及匹配部分相關(guān)內(nèi)容非常多,由于目前暫未涉及相關(guān)應用,如果你的應用中涉及相關(guān)內(nèi)容,有問題的話請在評論區(qū)留言.Have Fun With OpenCV-Python, 下期見。