這個利用了前面學到的SIFT特征檢測來實現的,然后這里主要就是引入了一個新的匹配器。這里
匹配是用KNN算法進行匹配的。下面來看下細節。
介紹函數
由于要頻繁展示,所以這里定義了一個函數。
def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)
導入圖片
if __name__ == "__main__":# 讀取圖像src1 = cv2.imread("zhiwen3.bmp")src2 = cv2.imread("zhiwen2.bmp")model = cv2.imread("zhiwen1.bmp")# 檢查圖像是否成功加載if src1 is None or src2 is None or model is None:print("錯誤: 無法加載圖像文件")else:# 顯示圖像(需要指定窗口名稱)cv_show('src1', src1)cv_show('src2', src2)cv_show('model', model)# 進行認證驗證result1 = verification(src1, model)result2 = verification(src2, model)print("src1驗證結果為:", result1)print("src2驗證結果為:", result2)
可以看到這里導入了三張圖片,一張目標圖片,兩張圖片。然后打印出結果
匹配函數
def verification(src, model):
# 創建SIFT特征提取器
sift = cv2.SIFT_create()
這里創建了一個SIFT特征提取器,前面一篇文章講過的。
? ? # 檢測關鍵點和計算描述符
kp1, des1 = sift.detectAndCompute(src, None) ?# 源圖像 ? ? ?第二個參數 掩膜
kp2, des2 = sift.detectAndCompute(model, None) ?# 模板圖像
然后這里返回了重要信息kp和des
kp
- ?位置信息? (
pt
):關鍵點在圖像中的坐標位置 (x, y)(重要,后面要用來標注出匹配點) - ?尺度信息? (
size
):關鍵點被檢測到的尺度級別 - ?方向信息? (
angle
):關鍵點的主方向,用于實現旋轉不變性 - ?響應強度? (
response
):表示該特征點的顯著程度
des
描述符的特點?:
- 通常是高維向量(如SIFT描述符是128維)
- 描述了關鍵點周圍區域的視覺外觀
- 對光照變化、旋轉、尺度變化具有一定的不變性
- 相似的圖像區域會產生相似的描述符向量
? ? # 檢查是否有足夠的特征點
if des1 is None or des2 is None or len(des1) < 2 or len(des2) < 2:
return "認證失敗(特征點不足)"
檢測看數量夠不夠匹配了,有時候特征太少,匹配不成功出現異常。
# 創建FLANN匹配器
flann = cv2.FlannBasedMatcher()
# 使用K近鄰匹配
matches = flann.knnMatch(des1, des2, k=2)
建立了一個FLANN匹配器,用于直接傳入兩個的描述符的特點,然后就可以匹配了
? ? # 應用Lowe's比率測試篩選優質匹配
good_matches = []
for m, n in matches:
if m.distance < 0.7 * n.distance: ?# 通常使用0.7-0.8的比率
good_matches.append(m)
這里我們前面參數k=2,是檢測我們這個點對應匹配兩個點,然后去計算這兩個點距離我們點的歐氏距離,然后得出如果兩個距離很接近就說明我們點匹配失敗。
? ? # 統計優質匹配數量
num = len(good_matches)
得到匹配點的個數,這里也可以看作匹配度
? ? # 可視化匹配結果(可選)
img_match = cv2.drawMatches(src, kp1, model, kp2, good_matches, None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv_show('匹配結果', img_match)
這里是可視化結果的一個方法。
? ? # 根據匹配數量判斷認證結果
if num >= 500: ?# 閾值可根據實際情況調整
result = "認證通過"
else:
result = "認證失敗"
? ? return f"{result} (匹配點: {num})"
總體代碼
import cv2
import numpy as np # 需要添加此導入def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)def verification(src, model):# 創建SIFT特征提取器sift = cv2.SIFT_create()# 檢測關鍵點和計算描述符kp1, des1 = sift.detectAndCompute(src, None) # 源圖像 第二個參數 掩膜kp2, des2 = sift.detectAndCompute(model, None) # 模板圖像# 檢查是否有足夠的特征點if des1 is None or des2 is None or len(des1) < 2 or len(des2) < 2:return "認證失敗(特征點不足)"# 創建FLANN匹配器flann = cv2.FlannBasedMatcher()# 使用K近鄰匹配matches = flann.knnMatch(des1, des2, k=2)# 應用Lowe's比率測試篩選優質匹配good_matches = []for m, n in matches:if m.distance < 0.7 * n.distance: # 通常使用0.7-0.8的比率good_matches.append(m)# 統計優質匹配數量num = len(good_matches)# 可視化匹配結果(可選)img_match = cv2.drawMatches(src, kp1, model, kp2, good_matches, None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv_show('匹配結果', img_match)# 根據匹配數量判斷認證結果if num >= 500: # 閾值可根據實際情況調整result = "認證通過"else:result = "認證失敗"return f"{result} (匹配點: {num})"if __name__ == "__main__":# 讀取圖像src1 = cv2.imread("zhiwen3.bmp")src2 = cv2.imread("zhiwen2.bmp")model = cv2.imread("zhiwen1.bmp")# 檢查圖像是否成功加載if src1 is None or src2 is None or model is None:print("錯誤: 無法加載圖像文件")else:# 顯示圖像(需要指定窗口名稱)cv_show('src1', src1)cv_show('src2', src2)cv_show('model', model)# 進行認證驗證result1 = verification(src1, model)result2 = verification(src2, model)print("src1驗證結果為:", result1)print("src2驗證結果為:", result2)