角點(diǎn)特征常常是圖像中獨(dú)特的存在如蚜,比如你在玩拼圖游戲時(shí)压恒,首先肯定會(huì)去找一些獨(dú)一無(wú)二的匹配項(xiàng),比如人像的眼睛错邦,嘴巴探赫,這些特征你很容易判斷哪些碎片應(yīng)該拼湊在一起,而相比之下撬呢,那些比較常見(jiàn)的特征你需要最后多次調(diào)整才能找到對(duì)的位置伦吠。角點(diǎn)特征就是這樣較獨(dú)特的存在,下圖中矩形的右上角點(diǎn)區(qū)域,無(wú)論你往哪個(gè)方向移動(dòng)讨勤,圖像的信息都會(huì)發(fā)生變化箭跳,而邊緣則沿某一個(gè)方向移動(dòng)時(shí)不會(huì)變化,至于矩形內(nèi)部區(qū)域潭千,則無(wú)論哪個(gè)方向移動(dòng)谱姓,圖像信息沒(méi)有變化[引用自官方教程]。
本文內(nèi)容涉及以下內(nèi)容(參考OpenCV3 計(jì)算機(jī)視覺(jué)第6章)
- Harris角點(diǎn)檢測(cè)
- Shi-Tomasi角點(diǎn)檢測(cè)(Harris的修改版)
- FAST角點(diǎn)檢測(cè)
有了特征點(diǎn)舔株,怎么用呢?你可以比對(duì)不同圖像的特征信息屡久,進(jìn)行目標(biāo)檢測(cè)蝶桶、圖像拼接等慨绳。在OpenCV中,可以通過(guò)下面的算子來(lái)進(jìn)行特征匹配:
- Brute-Force匹配法真竖,也稱暴力匹配法
- 基于FLANN的匹配法
1.使用Harris以及Shi-Tomasi算子獲取角點(diǎn)
注:這里采用Shi-Tomasi僅保留最好的12個(gè)角點(diǎn)信息(匹配比較好)脐雪,而harris輸出了全部角點(diǎn),圓圈顏色深表示該處檢測(cè)到的次數(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角點(diǎn)檢測(cè)
## src: 輸入圖像
## blockSize:鄰域大小
## ksize:Sobel算子中的核大小
## k :Harris檢測(cè)參數(shù),經(jīng)驗(yàn)范圍:[0.04, 0.06]战秋,值越大,假角點(diǎn)越少讨韭,不過(guò)可能會(huì)漏檢
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方法檢測(cè)
## src: 輸入圖像
## maxCorners:輸出的角點(diǎn)數(shù)目脂信,可以幫助你找到最佳的maxCorners個(gè)角點(diǎn),會(huì)將角點(diǎn)進(jìn)行排序
## qualityLevel:檢測(cè)質(zhì)量水平系數(shù)透硝,經(jīng)驗(yàn)值[0.01, 0.1]
## minDistance:最小的角點(diǎn)距離狰闪,小于該距離的角點(diǎn)會(huì)被忽視
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()
# 耗時(shí)情況:
# Harris Detection used :5.984783172607422 ms.
# goodFeaturesToTrack Detection used :9.972572326660156 ms.
補(bǔ)充:
1.關(guān)于參數(shù)ksize和檢測(cè)自由設(shè)置參數(shù)k,可參考博客【cornerHarris中的ksize和k是什么意思】--https://www.jb51.cc/python/533133.html
2.官方角點(diǎn)檢測(cè)參考鏈接: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 這個(gè)函數(shù)可以輸入mask信息
4.對(duì)于有更精細(xì)檢測(cè)需求的濒生,可以使用cornerSubPix()來(lái)檢測(cè)亞像素角點(diǎn)
對(duì)于FAST檢測(cè)角點(diǎn)的基本使用方法如下:
# 創(chuàng)建檢測(cè)器尝哆,大多數(shù)情況下閾值設(shè)置較大,太低會(huì)造成大量的假特征點(diǎn)
# 選擇非極大值抑制會(huì)使得特征點(diǎn)會(huì)少一些甜攀,避免一些假特征點(diǎn)
# type可選擇FAST_FEATURE_DETECTOR_TYPE_9_16,在像素周圍取16個(gè)點(diǎn),當(dāng)9個(gè)滿足條件,就是特征點(diǎn),除此之外琐馆,可選擇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獲取第一個(gè)特征點(diǎn)的坐標(biāo)信息
# detect第二個(gè)參數(shù)為特征點(diǎn)瘦麸,第三個(gè)參數(shù)為mask
kp = fast.detect(gray_img, None)
# 耗時(shí)情況
# FAST Detection used :0.9963512420654297 ms.??
參考博客:
1.OPENCV圖像特征點(diǎn)檢測(cè)與FAST算法https://www.cnblogs.com/dengxiaojun/p/5302778.html講解該函數(shù)的算法及參數(shù)
2.KeyPoint類參考博客:https://blog.csdn.net/leonardohaig/article/details/81289648
2.特征點(diǎn)匹配
你可以用特征點(diǎn)用在兩幅圖的信息比對(duì)上,這一點(diǎn)在圖像拼接中尤為重要,至于說(shuō)用特征進(jìn)行目標(biāo)檢測(cè),比如《OpenCV3 計(jì)算機(jī)視覺(jué)》中有將特征信息作為紋身信息的比對(duì).不過(guò),當(dāng)你的環(huán)境特征信息量比較多(比如風(fēng)景)的時(shí)候,匹配出錯(cuò)的概率非常大.# ORB特征點(diǎn)匹配
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])
# 按照特征點(diǎn)距離進(jìn)行排序,距離越小約好
# 參考博客: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 進(jìn)行特征提取的descriptor格式需要轉(zhuǎn)換下,否則是無(wú)法進(jì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)博客:
角點(diǎn)特征檢測(cè)之三(FLANN匹配)https://blog.csdn.net/wsp_1138886114/article/details/90578810
關(guān)于opencv-python的特征檢測(cè)及匹配部分相關(guān)內(nèi)容非常多谁撼,由于目前暫未涉及相關(guān)應(yīng)用,如果你的應(yīng)用中涉及相關(guān)內(nèi)容,有問(wèn)題的話請(qǐng)?jiān)谠u(píng)論區(qū)留言.Have Fun With OpenCV-Python, 下期見(jiàn)。