您好,登錄后才能下訂單哦!
鑒于即將啟程旅行,先上傳篇簡單的圖像檢索介紹,與各位一起學習opencv的同學共勉
一.特征檢測
圖片的特征主要分為角點,斑點,邊,脊向等,都是常用特征檢測算法所檢測到的圖像特征·
1.Harris角點檢測
先將圖片轉換為灰度模式,再使用以下函數檢測圖片的角點特征:
dst=cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
重點關注第三個參數,這里使用了Sobel算子,簡單來說,其取為3-31間的奇數,定義了角點檢測的敏感性,不同圖片需要進行調試。
k 是 Harris 角點檢測方程中的自由參數,取值參數為[0,04,0.06].
2.DoG角點檢測及SIFT特征變換
Harris角點檢測在面對圖像尺度性發生改變時極其容易丟失圖像細節,造成檢測失誤。因此在檢測圖像特征時,常常我們需要一些擁有尺度不變性的特征檢測算法。
DoG角點檢測即將兩幅圖像在不同參數下的高斯濾波結果相減,得到DoG圖。步驟:用兩個不同的5x5高斯核對圖像進行卷積,然后再相減的操作。重復三次得到三個差分圖A,B,C。計算出的A,B,C三個DOG圖中求圖B中是極值的點。圖B的點在當前由A,B,C共27個點組成的block中是否為極大值或者極小值。若滿足此條件則認為是角點。
SIFT對象會使用DoG檢測關鍵點,并對每個關鍵點周圍的區域計算特征向量。事實上他僅做檢測和計算,其返回值是關鍵點信息(關鍵點)和描述符。
#下列代碼即先創建一個SIFT對象,然后計算灰度圖像 sift = cv2.xfeatures2d.SIFT_create() keypoints, descriptor = sift.detectAndCompute(gray, None) #sift對象會使用DoG檢測關鍵點,對關鍵點周圍的區域計算向量特征,檢測并計算
需要注意的是,返回的是關鍵點和描述符
關鍵點是點的列表
描述符是檢測到的特征的局部區域圖像列表
介紹一下關鍵點的屬性:pt: 點的x y坐標 size: 表示特征的直徑 angle: 特征方向 response: 關鍵點的強度 octave: 特征所在金字塔層級,算法進行迭代的時候, 作為參數的圖像尺寸和相鄰像素會發生變化octave屬性表示檢測到關鍵點所在的層級 ID: 檢測到關鍵點的ID
SIFT特征不只具有尺度不變性,即使改變旋轉角度,圖像亮度或拍攝視角,仍然能夠得到好的檢測效果。
3.SURF提取和檢測特征
SURF是SIFT的加速版算法,采用快速Hessian算法檢測關鍵點
借用下度娘的說法:SURF算法原理:
1.構建Hessian矩陣構造高斯金字塔尺度空間
2.利用非極大值抑制初步確定特征點
3精確定位極值點
4選取特征點的主方向
5構造surf特征點描述算子
具體應用看代碼
import cv2 import numpy as np img = cv2.imread('/home/yc/Pictures/jianbin.jpg') #參數為hessian矩陣的閾值 surf = cv2.xfeatures2d.SURF_create(4000) #設置是否要檢測方向 surf.setUpright(True) #輸出設置值 print(surf.getUpright()) #找到關鍵點和描述符 key_query,desc_query = surf.detectAndCompute(img,None) img=cv2.drawKeypoints(img,key_query,img) #輸出描述符的個數 print(surf.descriptorSize()) cv2.namedWindow("jianbin",cv2.WINDOW_NORMAL) cv2.imshow('jianbin',img) cv2.waitKey(0) cv2.destroyAllWindows()
這是檢測效果,圖中已標志出特征點,不要問我為什么選這種鬼畜樣圖,可能是因為情懷(滑稽)
樣圖
需要注意的是,需要安裝之前版本的opencv-contrib庫才可以使用,surf及sift均受專利保護
4.orb特征提取
ORB算法使用FAST算法尋找關鍵點,然后使用Harris角點檢測找到這些點當中的最好的N個點,采用BRIEF描述子的特性。ORB算法處于起步階段,速度優于前兩種算法,也吸收了其優點,同時他是開源的。
# 創建ORB特征檢測器和描述符 orb = cv2.ORB_create() kp = orb.detect(img,None) # 對圖像檢測特征和描述符 kp, des = orb.compute(img, kp) #注意kp是一個包含若干點的列表,des對應每個點的描述符 是一個列表, 每一項都是檢測>到的特征的局部圖像
二、特征匹配
1.BF暴力匹配
暴力匹配的算法難以進行優化,是一種描述符匹配方法,將每個對應的描述符的特征進行比較,每次比較給出一個距離值,最好的結果賊被認為是一個匹配。
# 暴力匹配BFMatcher,遍歷描述符,確定描述符是否匹配,然后計算匹配距離并排序 # BFMatcher函數參數: # normType:NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2。 # NORM_L1和NORM_L2是SIFT和SURF描述符的優先選擇,NORM_HAMMING和NORM_HAMMING2是用于ORB算法 bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True) matches = bf.match(des1,des2) matches = sorted(matches, key = lambda x:x.distance) # matches是DMatch對象,具有以下屬性: # DMatch.distance - 描述符之間的距離。 越低越好。 # DMatch.trainIdx - 訓練描述符中描述符的索引 # DMatch.queryIdx - 查詢描述符中描述符的索引 # DMatch.imgIdx - 訓練圖像的索引。
2.K-最近鄰匹配
KNN算法可能是最簡單的機器學習算法,即給定一個已訓練的數據集,對新的輸入實例,在訓練數據集中找到與該實例最鄰近的K個實例,這K個實例的多數屬于某個類,則判定該輸入實例同屬此類。
概念比較冗長,大致可以理解為如果一個樣本在特征空間中的k個最相似(即特征空間中最鄰近)的樣本中的大多數屬于某一個類別,則該樣本也屬于這個類別,我個人簡單的理解為由那離自己最近的K個點來投票決定待分類數據歸為哪一類。
這里我們直接調用opencv庫中的KNN函數,使用較簡單。該KNN匹配利用BF匹配后的數據進行匹配。
完整代碼:
# coding:utf-8 import cv2 # 按照灰度圖像讀入兩張圖片 img1 = cv2.imread("/home/yc/Pictures/cat.jpg", cv2.IMREAD_GRAYSCALE) img2 = cv2.imread("/home/yc/Pictures/cat2.jpg", cv2.IMREAD_GRAYSCALE) # 獲取特征提取器對象 orb = cv2.ORB_create() # 檢測關鍵點和特征描述 keypoint1, desc1 = orb.detectAndCompute(img1, None) keypoint2, desc2 = orb.detectAndCompute(img2, None) """ keypoint 是關鍵點的列表 desc 檢測到的特征的局部圖的列表 """ # 獲得knn檢測器 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = bf.knnMatch(desc1, desc2, k=1) """ knn 匹配可以返回k個最佳的匹配項 bf返回所有的匹配項 """ # 畫出匹配結果 img3 = cv2.drawMatchesKnn(img1, keypoint1, img2, keypoint2, matches, img2, flags=2) cv2.imshow("cat", img3) cv2.waitKey() cv2.destroyAllWindows()
也許這里得到的結果與match函數所得到的結果差距不大,但二者主要區別是KnnMatch所返回的是K個匹配值,可以容許我們繼續處理,而match返回最佳匹配。
以下為樣圖
cat
實現簡單的圖像檢索功能時,此類特征匹配算法對硬件的要求較低,效率較高,但是準確度有待考量
與一起學習opencv的同學共勉,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。