角点检测:角点(Corner)是图像中在两个或多个方向上灰度值发生剧烈变化的点。这些点通常包含丰富的信息,适用于特征匹配、目标跟踪、三维重建等任务。
python
#------------------角点检测------------------------
#角点指图像中局部区域与周围区域有较大灰度变化的点或像素。
#角点指图像中局部区域与周围区域有较大灰度变化的点或像素。
# cornerHarris(img,blocksize,ksize, k[, dst[, borderType]])-> dst
# img:输入图像。
# blockSize:角点检测中要考虑的领域大小。
# ksize:Sobel求导中使用的窗大小。
# k: Harris角点检测方程中的自由参数,取值参数为[0.04,0.06]。
# dst:返回numpy.ndarray对象,大小和src相同,值越大,对应像素点是角的概率越高
img = cv2.imread('phone.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.cornerHarris(gray,4,3,0.04)
#标记检测到的角点
img[dst >0.05 * dst.max()]=[0,0,255]
# 这里通过对角点响应进行闽值处理,标记出检测到的角点。
# 0.05 * dst.max() 是一个值,大于这个值的像素点会被标记为红色。
cv2.imshow('img',img)
cv2.waitKey(0)

特征提取:是指从原始数据中抽取关键信息,将其转化为具有判别性的特征向量的过程。
目的
降低数据维度,保留最相关的信息,提高模型效率与泛化能力。
python
#'''''''''''------------特征提取------------------
#检测图像中的关键点
#cv2.SIFT_create() #cv2.xfeatures2d.SIFT_create()#创建一个sift特征的提取对象
#sift.detect(img)在图像中查找关键点
phone = cv2.imread('phone.png')
phone_gray = cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT_create()#sift对象
kp = sift.detect(phone_gray)
# kp.pt:关键点的(x,y)
# 坐标。
# kp.size:关键点的大小(尺度)
# kp.angle:关键点的方间。
# kp.response:关键点的响应值。
# kp.octave:关键点所在的金字塔层级。
#查找关键点
#drawKeypoints(image,keypoints, outImage, color=None, flags=None)
# image:原始图片
# keypoints:从原图中获得的关键点,这也是画图时所用到的数
# outputimage:输出图像,可以是原始图片,也可以是None
# color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
# flags:绘图功能的标识设置 绘制富有信息的关键点。
phone_sift =cv2.drawKeypoints(phone,kp,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('phone',phone_sift)
cv2.waitKey(0)
# 使用sift.compute()计算关键点描述符,方便后期的特征匹配
kp,des =sift.compute(phone,kp)
print(np.array(kp).shape,des.shape)
# 输出关键点的形状和描述待的形状。
# np.array(kp).shape表不关键点的数量和属性
# des.shape 表示描述符的数量和属性。
运行结果:

基于 SIFT 特征匹配的图像验证程序,核心用途是判断两张指纹(或其他)图像是否为同一目标
核心流程:
python
读取待验证图像(src1/src2)和模板图像(model)→
用SIFT提取所有图像的特征点+特征描述符 →
用FLANN匹配器做K近邻匹配(每个特征点找最近的2个匹配)→
通过Lowe's比率测试(0.8阈值)筛选有效匹配 →
统计有效匹配数,≥500则判定"认证通过",否则"认证失败"
| 代码段 | 功能 |
|---|---|
cv_show(name,img) |
封装图像显示函数(但注释了cv2.waitKey(0),是关键问题) |
verification(src,model) |
核心验证函数:完成特征提取、匹配、筛选、结果判定 |
sift = cv2.SIFT_create() |
创建 SIFT 特征提取器(提取具有尺度 / 旋转不变性的特征点) |
kp1,des1 = sift.detectAndCompute(...) |
检测图像关键点 + 计算 128 维特征描述符(匹配的核心依据) |
flann = cv2.FlannBasedMatcher() |
创建 FLANN 匹配器(高效匹配特征描述符,比暴力匹配快) |
matches = flann.knnMatch(des1,des2,k=2) |
K 近邻匹配:为 src 的每个特征点找 model 中最像的 2 个特征点 |
if m.distance<0.8*n.distance |
Lowe's 比率测试:过滤误匹配(最佳匹配远优于次佳匹配才有效) |
num >=500 |
自定义阈值:匹配数足够多则判定为同一图像(指纹认证通过) |
| 主函数 | 读取图像、调用验证函数、输出认证结果 |
代码:
python
import cv2
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)
#创建FLANN匹配器
flann =cv2.FlannBasedMatcher()
#使用K近邻匹配(des1中的每个描述与des2中的最近两个描述进行匹配)
matches = flann.knnMatch(des1,des2,k=2)
#distance :匹配的特征点描述符的欧氏距离,数值越小也就说明俩个特征点越相近
#queryIdx: 测试图像的特征描述的下标(第几个特征点描述符),同时也是描述符对应特征点的下标。
#也是描述符对应特征点的下标。
#进行比较筛选
ok = []
for m,n in matches:
#根据Lowe's比率测试,选择最佳匹配
if m.distance<0.8*n.distance:
ok.append((m,n))
#统计通过筛选的匹配数量
num = len(ok)
if num >=500:
result="认证通过"
else:
result="认证失败"
return result
if __name__=="__main__":
src1 = cv2.imread("src1.bmp")
cv_show('src1',src1)
src2 = cv2.imread("src2.bmp")
cv_show('src2',src2)
model = cv2.imread("model.bmp")
cv_show('model',model)
result1=verification(src1,model)
result2=verification(src2,model)
print("src1验证结果为:",result1)
print("src2验证结果为:",result2)
cv2.waitKey(0)
#
运行结果:




实现一个自动化的指纹识别系统:
计算指纹匹配个数
python
import os
import cv2
'''=====================计算两个指纹间匹配点的个数================='''
def getNum(src,model):
# 1. 读取指纹图像(src:待识别指纹路径,model:模板指纹路径)
img1=cv2.imread(src)
img2=cv2.imread(model)
# 2. 创建SIFT特征提取器(尺度不变特征变换,抗旋转/尺度变化)
sift=cv2.SIFT_create()
# 3. 检测关键点+计算特征描述符(128维向量,匹配的核心依据)
kp1,des1 = sift.detectAndCompute(img1,None)
kp2,des2 = sift.detectAndCompute(img2,None)
# 4. 创建FLANN匹配器(高效近邻匹配,适合大规模特征集)
flann = cv2.FlannBasedMatcher()
# 5. K近邻匹配(k=2:为每个特征点找最近的2个匹配)
matches = flann.knnMatch(des1,des2,k=2)
# 6. Lowe's比率测试筛选有效匹配(过滤误匹配)
ok=[]
for m,n in matches:
# 核心逻辑:最佳匹配距离 < 0.8*次佳匹配距离,判定为有效匹配
if m.distance<0.8*n.distance:
ok.append(m)
# 7. 返回有效匹配点数量
num =len(ok)
return num
遍历指纹库获取最优匹配 ID
python
#'''''''''''''''''''获取指纹编号'''''''''''''''''''''''''
def getID(src,database):
max=0
for file in os.listdir(database):
model =os.path.join(database,file)
num = getNum(src,model)
print("文件名:",file,'匹配点个数:',num)
if num >max:
max = num
name =file
ID = name[0]
if max<200:
ID =9999
return ID
根据指纹编号,获取对应名字
python
# '''----------------根据指纹编号,获取对应名字----------------'''
def getName(ID):
nameID={0:'张三',1:'李四',2:'王五',3:'赵六',4:'朱老七',5:'钱八',
6:'曹九',7:'王二麻子',8:'andy',9:'Anna',9999:"没找到"}
name = nameID.get(int(ID))
return name
"""================主函数==========================="""
if __name__=="__main__":
src ="src.BMP"
database ="database"
ID = getID(src,database)
name = getName(ID)
print("识别结果为:",name)
运行结果:

指纹验证案例中,指纹1与模板图片匹配成功了,分别在两图内标出匹配成功点的坐标
要求:匹配结果最近的distance小于次接近distance的0.4
提示:cv2.circle(src, (x,y), 3, (0, 0, 255), -1),绘制实心圆
代码如下:
python
import cv2
import numpy as np
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def verification_and_mark(src, model, threshold=0.4):
# -------------------------- 1. 特征提取(你学的SIFT) --------------------------
sift = cv2.SIFT_create()
# 检测关键点 + 计算描述符(源图src1、模板图model)
kp1, des1 = sift.detectAndCompute(src, None)
kp2, des2 = sift.detectAndCompute(model, None)
# -------------------------- 2. FLANN匹配(你学的K近邻) --------------------------
# 补充FLANN参数,避免匹配报错
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# K=2近邻匹配:每个特征找最近的2个匹配
matches = flann.knnMatch(des1, des2, k=2)
# -------------------------- 3. 按作业要求筛选匹配(0.4阈值) --------------------------
good_matches = []
src_points = [] # 存储src1上的匹配点坐标
model_points = [] # 存储model上的匹配点坐标
for m, n in matches:
# 作业要求:最近距离 < 次近距离 × 0.4
if m.distance < threshold * n.distance:
good_matches.append(m)
# 提取匹配点的坐标(kp.pt返回(x,y)浮点数,转整数用于画圆)
src_x, src_y = kp1[m.queryIdx].pt
model_x, model_y = kp2[m.trainIdx].pt
src_points.append((int(src_x), int(src_y)))
model_points.append((int(model_x), int(model_y)))
# -------------------------- 4. 标注匹配点(作业要求的cv2.circle) --------------------------
# 复制原图,避免修改原图像
src_marked = src.copy()
model_marked = model.copy()
# 在src1上画红色实心圆
for (x, y) in src_points:
cv2.circle(src_marked, (x, y), 3, (0, 0, 255), -1) # 3是圆半径,-1实心
# 在model上画红色实心圆
for (x, y) in model_points:
cv2.circle(model_marked, (x, y), 3, (0, 0, 255), -1)
# -------------------------- 5. 结果输出 --------------------------
print(f"符合0.4阈值的有效匹配点数量:{len(good_matches)}")
print("src1匹配点坐标(前10个示例):", src_points[:10])
print("model匹配点坐标(前10个示例):", model_points[:10])
# 显示标注后的图(对应你提供的效果图)
cv_show("Marked src1", src_marked)
cv_show("Marked model", model_marked)
# 返回匹配结果(认证通过/失败,可自定义阈值)
return "认证通过" if len(good_matches) >= 20 else "认证失败"
# -------------------------- 主函数(直接运行) --------------------------
if __name__ == "__main__":
# 读取你的指纹图(替换为你的实际路径)
src1 = cv2.imread("src1.bmp")
model = cv2.imread("model.bmp")
# 执行验证+标注(阈值设为作业要求的0.4)
result = verification_and_mark(src1, model, threshold=0.4)
print("src1验证结果为:", result)
运行结果:

