Python OpenCV學(xué)習(xí)之特征點(diǎn)檢測(cè)與匹配詳解
背景
提取圖像的特征點(diǎn)是圖像領(lǐng)域中的關(guān)鍵任務(wù),不管在傳統(tǒng)還是在深度學(xué)習(xí)的領(lǐng)域中,特征代表著圖像的信息,對(duì)于分類、檢測(cè)任務(wù)都是至關(guān)重要的;
特征點(diǎn)應(yīng)用的一些場(chǎng)景:
圖像搜索:以圖搜圖(電商、教育領(lǐng)域)
圖像拼接:全景拍攝(關(guān)聯(lián)圖像拼接)
拼圖游戲:游戲領(lǐng)域
一、Harris角點(diǎn)
哈里斯角點(diǎn)檢測(cè)主要有以下三種情況:
- 光滑區(qū)域:無(wú)論向哪個(gè)方向移動(dòng),衡量系數(shù)不變;
- 邊緣區(qū)域:垂直邊緣移動(dòng)時(shí),衡量系數(shù)變化強(qiáng)烈;
- 角點(diǎn)區(qū)域:不管往哪個(gè)方向移動(dòng),衡量系數(shù)變化強(qiáng)烈;
函數(shù)原型:
cornerHarris(img,blockSize,ksize,k)
blockSize
:檢測(cè)窗口大??;
k
:權(quán)重系數(shù),一般取0.02~0.04之間;
代碼案例:
img = cv2.imread('chess.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) dst = cv2.cornerHarris(gray, 2, 3, 0.04) img[dst > 0.01*dst.max()] = (0, 0, 255) cv2.imshow('harris', img) cv2.waitKey(0)
二、Shi-Tomasi角點(diǎn)檢測(cè)
說(shuō)明:是Harris角點(diǎn)檢測(cè)的改進(jìn),在Harris中需要知道k這個(gè)經(jīng)驗(yàn)值,而在Shi-Tomasi不需要;
函數(shù)原型:
goodFeaturesToTrack(img,…)
maxCorners
:角點(diǎn)的最大數(shù)量,值為0表示所有;
qualityLevel
:角點(diǎn)的質(zhì)量,一般在0.01~0.1之間(低于的過(guò)濾掉);
minDistance
:角點(diǎn)之間最小歐式距離,忽略小于此距離的點(diǎn);
mask
:感興趣區(qū)域;
useHarrisDetector
:是否使用Harris算法(默認(rèn)為false)
代碼案例:
img = cv2.imread('chess.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) dst = cv2.goodFeaturesToTrack(gray, 1000, 0.01, 10) dst = np.int0(dst) ? ? ? ? ? ?# 實(shí)際上也是np.int64 for i in dst: ? ? x, y = i.ravel() ? ? ? ? # 數(shù)組降維成一維數(shù)組(inplace的方式) ? ? cv2.circle(img, (x, y), 3, (0, 0, 255), -1) cv2.imshow('harris', img) cv2.waitKey(0)
本質(zhì)上和Harris角點(diǎn)檢測(cè)相同,效果會(huì)好一些,角點(diǎn)數(shù)量會(huì)多一些;
三、SIFT關(guān)鍵點(diǎn)
中文簡(jiǎn)譯:與縮放無(wú)關(guān)的特征轉(zhuǎn)換;
說(shuō)明:Harris角點(diǎn)檢測(cè)具有旋轉(zhuǎn)不變性,也就是旋轉(zhuǎn)圖像并不會(huì)影響檢測(cè)效果;但其并不具備縮放不變性,縮放大小會(huì)影響角點(diǎn)檢測(cè)的效果;SIFT具備縮放不變性的性質(zhì);
實(shí)現(xiàn)步驟:
創(chuàng)建SIFT對(duì)象 —— 進(jìn)行檢測(cè)(sift.detect) —— 繪制關(guān)鍵點(diǎn)(drawKeypoints)
代碼案例:
img = cv2.imread('chess.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() kp = sift.detect(gray, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 cv2.drawKeypoints(gray, kp, img) cv2.imshow('sift', img) cv2.waitKey(0)
四、SIFT描述子
首先需要說(shuō)明,關(guān)鍵點(diǎn)和描述子是兩個(gè)概念;
關(guān)鍵點(diǎn):位置、大小和方向;
關(guān)鍵點(diǎn)描述子:記錄了關(guān)鍵點(diǎn)周圍對(duì)其有貢獻(xiàn)的像素點(diǎn)的一組向量值,其不受仿射變換,光照變換等影響;描述子的作用就是用于特征匹配;
同時(shí)計(jì)算關(guān)鍵點(diǎn)和描述子的函數(shù)(主要使用):
detectAndCompute(img,…)
代碼案例:
img = cv2.imread('chess.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() kp, dst = sift.detectAndCompute(gray, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域
得到的dst即為描述子的信息;
五、SURF
中譯:加速的魯棒性特征檢測(cè);
說(shuō)明:SIFT最大的缺點(diǎn)是速度慢,因此才會(huì)有SURF(速度快);
實(shí)現(xiàn)步驟與SIFT一致,代碼如下:
surf = cv2.xfeatures2d.SURF_create() kp, dst = surf.detectAndCompute(gray, None) # 第二個(gè)參數(shù)為mask區(qū)域 cv2.drawKeypoints(gray, kp, img)
由于安裝的opencv-contrib版本過(guò)高(有版權(quán)問題),已經(jīng)不支持該功能了,在此就不作展示了;
六、ORB
說(shuō)明:最大的優(yōu)勢(shì)就是做到實(shí)時(shí)檢測(cè),缺點(diǎn)就是缺失了很多信息(準(zhǔn)確性下降);
主要是兩個(gè)技術(shù)的結(jié)合:FAST(特征點(diǎn)實(shí)時(shí)檢測(cè))+ BRIEE(快速描述子建立,降低特征匹配時(shí)間)
使用步驟與之前的SIFT一致,代碼如下:
img = cv2.imread('chess.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) orb = cv2.ORB_create() kp, dst = orb.detectAndCompute(gray, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 cv2.drawKeypoints(gray, kp, img) cv2.imshow('orb', img) cv2.waitKey(0)
可以看出,相比于SIFT以及SURF關(guān)鍵點(diǎn)變少了,但是其速度有了很大提升;
七、暴力特征匹配(BF)
匹配原理:類似于窮舉匹配機(jī)制,使用第一組中每個(gè)特征的描述子與第二組中的進(jìn)行匹配,計(jì)算相似度,返回最接近的匹配項(xiàng);
實(shí)現(xiàn)步驟:
創(chuàng)建匹配器:BFMatcher(normType,crossCheck)
進(jìn)行特征匹配:bf.match(des1,des2)
繪制匹配點(diǎn):cv2.drawMatches(img1,kp1,img2,kp2)
代碼案例:
img1 = cv2.imread('opencv_search.png') img2 = cv2.imread('opencv_orig.png') g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) sift = cv2.SIFT_create() kp1, dst1 = sift.detectAndCompute(g1, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 kp2, dst2 = sift.detectAndCompute(g2, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 bf = cv2.BFMatcher_create(cv2.NORM_L1) match = bf.match(dst1, dst2) img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None) cv2.imshow('result', img3) cv2.waitKey(0)
從上圖可看出,匹配的效果還是不錯(cuò)的,只有一個(gè)特征點(diǎn)匹配錯(cuò)誤;
八、FLANN特征匹配
優(yōu)點(diǎn):在進(jìn)行批量特征匹配時(shí),F(xiàn)LANN速度更快;
缺點(diǎn):由于使用的時(shí)鄰近近似值,所有精度較差;
實(shí)現(xiàn)步驟與暴力匹配法一致,代碼如下:
img1 = cv2.imread('opencv_search.png') img2 = cv2.imread('opencv_orig.png') g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) sift = cv2.SIFT_create() kp1, dst1 = sift.detectAndCompute(g1, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 kp2, dst2 = sift.detectAndCompute(g2, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 index_params = dict(algorithm = 1, trees = 5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matchs = flann.knnMatch(dst1, dst2, k=2) good = [] for i, (m, n) in enumerate(matchs): ? ? if m.distance < 0.7 * n.distance: ? ? ? ? good.append(m) img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None) cv2.imshow('result', img3) cv2.waitKey(0)
上圖可以看出,匹配的特征點(diǎn)數(shù)量相比暴力匹配明顯變少了,但速度會(huì)快很多;
九、圖像查找
實(shí)現(xiàn)原理:特征匹配 + 單應(yīng)性矩陣;
單應(yīng)性矩陣原理介紹:
上圖中表示從兩個(gè)不同角度對(duì)原圖的拍攝,其中H為單應(yīng)性矩陣,可通過(guò)該矩陣將圖像進(jìn)行轉(zhuǎn)換;
下面使用兩個(gè)函數(shù)實(shí)現(xiàn)圖像查找的功能:
findHomography():獲得單應(yīng)性矩陣;
perspectivveTransform():仿射變換函數(shù);
代碼實(shí)現(xiàn)如下:
img1 = cv2.imread('opencv_search.png') img2 = cv2.imread('opencv_orig.png') g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) sift = cv2.SIFT_create() kp1, dst1 = sift.detectAndCompute(g1, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 kp2, dst2 = sift.detectAndCompute(g2, None) ? ? ?# 第二個(gè)參數(shù)為mask區(qū)域 index_params = dict(algorithm = 1, trees = 5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matchs = flann.knnMatch(dst1, dst2, k=2) good = [] for i, (m, n) in enumerate(matchs): ? ? if m.distance < 0.7 * n.distance: ? ? ? ? good.append(m) if len(good) >= 4: ?? ?# 獲得源和目標(biāo)點(diǎn)的數(shù)組 ? ? srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2) ? ? dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2) ? ?? ? ? # 獲得單應(yīng)性矩陣H ? ? H, _ = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0) ? ? h, w = img1.shape[:2] ? ? pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2) ? ? # 進(jìn)行放射變換 ? ? dst = cv2.perspectiveTransform(pts, H) ? ?? ? ? # 繪制查找到的區(qū)域 ? ? cv2.polylines(img2, [np.int32(dst)], True, (0,0,255)) else: ? ? print('good must more then 4.') ? ? exit() ? ?? img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None) cv2.imshow('result', img3) cv2.waitKey(0)
總結(jié)
本篇主要介紹了特征點(diǎn)檢測(cè)和匹配,其中重要的部分時(shí)SIFT算法以及FLANN算法;通過(guò)所學(xué)的知識(shí),可以簡(jiǎn)單實(shí)現(xiàn)一個(gè)圖像查找的功能,也就是找子圖的功能。甚至可以目標(biāo)識(shí)別的效果;當(dāng)然這里需要的是完全一致的,不同于深度學(xué)習(xí)中的目標(biāo)識(shí)別任務(wù)
以上就是Python OpenCV學(xué)習(xí)之特征點(diǎn)檢測(cè)與匹配詳解的詳細(xì)內(nèi)容,更多關(guān)于Python OpenCV特征點(diǎn)檢測(cè)與匹配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Python如何使用PyBuilder從零開始構(gòu)建項(xiàng)目
PyBuilder是一個(gè)用于構(gòu)建Python項(xiàng)目的工具,它提供了一種簡(jiǎn)單而強(qiáng)大的方式來(lái)管理項(xiàng)目的依賴、運(yùn)行測(cè)試、生成文檔等任務(wù),下面就跟隨小編一起來(lái)學(xué)習(xí)一下如何使用PyBuilder構(gòu)建項(xiàng)目吧2024-03-03web.py在SAE中的Session問題解決方法(使用mysql存儲(chǔ))
這篇文章主要介紹了web.py在SAE中的Session問題解決方法(使用mysql存儲(chǔ)),本文直接給出實(shí)現(xiàn)代碼,代碼中包含詳細(xì)注釋,需要的朋友可以參考下2015-06-06Python+?Flask實(shí)現(xiàn)Mock?Server詳情
這篇文章主要介紹了Python+?Flask實(shí)現(xiàn)Mock?Server詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09Python3.5 Json與pickle實(shí)現(xiàn)數(shù)據(jù)序列化與反序列化操作示例
這篇文章主要介紹了Python3.5 Json與pickle實(shí)現(xiàn)數(shù)據(jù)序列化與反序列化操作,結(jié)合實(shí)例形式分析了Python3.5使用Json與pickle模塊實(shí)現(xiàn)json格式數(shù)據(jù)的序列化及反序列化操作相關(guān)步驟與注意事項(xiàng),需要的朋友可以參考下2019-04-04python利用 pytesseract快速識(shí)別提取圖片中的文字((圖片識(shí)別)
本文介紹了tesseract的python調(diào)用,也就是pytesseract庫(kù),其中還有一些其他的內(nèi)容并沒有涉及,僅涉及到了圖片提取文字,如果你對(duì)其感興趣,可以深入探索一下,也希望能和我探討一下2022-11-11用Python實(shí)現(xiàn)2024年春晚劉謙魔術(shù)
昨晚春晚上劉謙的兩個(gè)魔術(shù)表演都非常精彩,忍不住用編程去模擬一下這個(gè)過(guò)程,所以本文給大家用Python實(shí)現(xiàn)2024年春晚劉謙魔術(shù),文中通過(guò)代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02