当前位置:   article > 正文

2021WSB-day2-4: Raffaele教授演示利用OpenCV和Python实现一个指纹识别系统 (含代码) part6_raffaele教授指纹

raffaele教授指纹


听百家之言,集百家智慧,站在巨人肩上攀登


本文旨在帮助大家理解指纹识别的机制和一些算法原理,有一个好的理解之后,读者朋友们需要自己做出一些修改,提出自己的想法。
特别说明,本文依据Raffaele教授的workshop整理而成,读者朋友们不要草率复制粘贴作为自己的论文或者报告。

前两步参考前文1

指纹的分割

参考前文1

估计局部脊线的方向

参考前文1

计算局部脊线的频率

参考前文2

指纹增强处理

参考前文3

细节点提取

参考前文4

细节点方向计算

参考前文4

基于Minutia Cylinder-Code的指纹特征表征

Minutia Cylinder-Code (MCC) 是指纹里面,最最最有名的指纹特征表征。MCC发表在IEEE tPAMI,影响非常大。感兴趣可以查询原文,本文不再解释(后面有机会可以详细介绍一下MCC):

Minutia Cylinder-Code: a new representation and matching technique for fingerprint recognition", IEEE tPAMI 2010

总结起来:

  • MCC为最为有名的细节点匹配方法
  • MCC提出了一种基于三维数据结构的圆柱编码算法,其从细节的距离和角度出发,构造了圆柱编码
  • 为一种多级的指纹匹配方法,其不仅使用了细节点特征也使用了方向场等特征
  • 是一种局部结构,也是3D结构

在这里插入图片描述

以下是代码:

# Compute the cell coordinates of a generic local structure
# 计算
mcc_radius = 70
mcc_size = 16

g = 2 * mcc_radius / mcc_size
x = np.arange(mcc_size)*g - (mcc_size/2)*g + g/2
y = x[..., np.newaxis]
iy, ix = np.nonzero(x**2 + y**2 <= mcc_radius**2)
ref_cell_coords = np.column_stack((x[ix], x[iy]))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
mcc_sigma_s = 7.0
mcc_tau_psi = 400.0
mcc_mu_psi = 1e-2

def Gs(t_sqr):
    """Gaussian function with zero mean and mcc_sigma_s standard deviation, see eq. (7) in MCC paper"""
    return np.exp(-0.5 * t_sqr / (mcc_sigma_s**2)) / (math.tau**0.5 * mcc_sigma_s)

def Psi(v):
    """Sigmoid function that limits the contribution of dense minutiae clusters, see eq. (4)-(5) in MCC paper"""
    return 1. / (1. + np.exp(-mcc_tau_psi * (v - mcc_mu_psi)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
# n: number of minutiae
# c: number of cells in a local structure

xyd = np.array([(x,y,d) for x,y,_,d in valid_minutiae]) # matrix with all minutiae coordinates and directions (n x 3)

# rot: n x 2 x 2 (rotation matrix for each minutia)
d_cos, d_sin = np.cos(xyd[:,2]).reshape((-1,1,1)), np.sin(xyd[:,2]).reshape((-1,1,1))
rot = np.block([[d_cos, d_sin], [-d_sin, d_cos]])

# rot@ref_cell_coords.T : n x 2 x c
# xy : n x 2
xy = xyd[:,:2]
# cell_coords: n x c x 2 (cell coordinates for each local structure)
cell_coords = np.transpose(rot@ref_cell_coords.T + xy[:,:,np.newaxis],[0,2,1])

# cell_coords[:,:,np.newaxis,:]      :  n x c  x 1 x 2
# xy                                 : (1 x 1) x n x 2
# cell_coords[:,:,np.newaxis,:] - xy :  n x c  x n x 2
# dists: n x c x n (for each cell of each local structure, the distance from all minutiae)
dists = np.sum((cell_coords[:,:,np.newaxis,:] - xy)**2, -1)

# cs : n x c x n (the spatial contribution of each minutia to each cell of each local structure)
cs = Gs(dists)
diag_indices = np.arange(cs.shape[0])
cs[diag_indices,:,diag_indices] = 0 # remove the contribution of each minutia to its own cells

# local_structures : n x c (cell values for each local structure)
local_structures = Psi(np.sum(cs, -1))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

可以可视化看以下计算出来的MCC是什么样子的,这个真的是很棒呀,可以清楚的看大细节点之间的关系。

@interact(i=(0,len(valid_minutiae)-1))
def test(i=0):
    show(draw_minutiae_and_cylinder(fingerprint, ref_cell_coords, valid_minutiae, local_structures, i))
  • 1
  • 2
  • 3

在这里插入图片描述

MCC匹配

MCC匹配在18年本人也曾发文分析过,请看minutia cylinder code MCC lSSR 匹配算法

在这一些列博文教程中,我们从一张指纹图片开始,得到了细节点,以及他们的MCC表征

我们可以打印输出相关的信息:

print(f"""Fingerprint image: {fingerprint.shape[1]}x{fingerprint.shape[0]} pixels
Minutiae: {len(valid_minutiae)}
Local structures: {local_structures.shape}""")
  • 1
  • 2
  • 3

输出:

Fingerprint image: 256x364 pixels
Minutiae: 52
Local structures: (52, 208)
  • 1
  • 2
  • 3

我们重命名一下:

f1, m1, ls1 = fingerprint, valid_minutiae, local_structures
  • 1

我们取另外一个指纹(提取保存好的):

ofn = 'samples/sample_1_2' # Fingerprint of the same finger
#ofn = 'samples/sample_2' # Fingerprint of a different finger
f2, (m2, ls2) = cv.imread(f'{ofn}.png', cv.IMREAD_GRAYSCALE), np.load(f'{ofn}.npz', allow_pickle=True).values()
  • 1
  • 2
  • 3

两个局部结构 r 1 r_1 r1 r 2 r_2 r2的相似度可以通过计算他们的欧氏距离来确定:

s i m i l a r i t y ( r 1 , r 2 ) = 1 − ∥ r 1 − r 2 ∥ ∥ r 1 ∥ + ∥ r 2 ∥ similarity(r_1, r_2) = 1 - \frac {\| r_1 - r_2 \|}{\|r_1\| + \|r_2\|} similarity(r1,r2)=1r1+r2r1r2

以下的代码计算ls1 以及 ls2之间的均一化欧氏距离:

# Compute all pairwise normalized Euclidean distances between local structures in v1 and v2
# ls1                       : n1 x  c
# ls1[:,np.newaxis,:]       : n1 x  1 x c
# ls2                       : (1 x) n2 x c
# ls1[:,np.newaxis,:] - ls2 : n1 x  n2 x c 
# dists                     : n1 x  n2
dists = np.sqrt(np.sum((ls1[:,np.newaxis,:] - ls2)**2, -1))
dists /= (np.sqrt(np.sum(ls1**2, 1))[:,np.newaxis] + np.sqrt(np.sum(ls2**2, 1))) # Normalize as in eq. (17) of MCC paper
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

接下来,我们通过Local Similarity Sort (LSS)比较两个指纹的相似度(可以参考MCC文章查看相似) 。
总而言之,就是选择前p个最高的相似度,然后计算均值作为最终的相似度。

# Select the num_p pairs with the smallest distances (LSS technique)
num_p = 5 # For simplicity: a fixed number of pairs
pairs = np.unravel_index(np.argpartition(dists, num_p, None)[:num_p], dists.shape)
score = 1 - np.mean(dists[pairs[0], pairs[1]]) # See eq. (23) in MCC paper
print(f'Comparison score: {score:.2f}') # 结果0.78
  • 1
  • 2
  • 3
  • 4
  • 5

我们也可以可视化检查下:

@interact(i = (0,len(pairs[0])-1), show_local_structures = False)
def show_pairs(i=0, show_local_structures = False):
    show(draw_match_pairs(f1, m1, ls1, f2, m2, ls2, ref_cell_coords, pairs, i, show_local_structures))
  • 1
  • 2
  • 3

在这里插入图片描述

总结

本文使用python实现了MCC和MCC的匹配,最后计算出不同指纹的相似度。

Charles@Shenzhen, 20210304,夜

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/397009
推荐阅读
相关标签
  

闽ICP备14008679号