赞
踩
前两步参考前文1。
参考前文1。
参考前文1。
参考前文2。
参考前文3。
参考前文4。
参考前文4。
Minutia Cylinder-Code (MCC) 是指纹里面,最最最有名的指纹特征表征。MCC发表在IEEE tPAMI,影响非常大。感兴趣可以查询原文,本文不再解释(后面有机会可以详细介绍一下MCC):
Minutia Cylinder-Code: a new representation and matching technique for fingerprint recognition", IEEE tPAMI 2010
总结起来:
以下是代码:
# 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]))
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)))
# 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))
可以可视化看以下计算出来的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))
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}""")
输出:
Fingerprint image: 256x364 pixels
Minutiae: 52
Local structures: (52, 208)
我们重命名一下:
f1, m1, ls1 = fingerprint, valid_minutiae, local_structures
我们取另外一个指纹(提取保存好的):
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()
两个局部结构 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)=1−∥r1∥+∥r2∥∥r1−r2∥
以下的代码计算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
接下来,我们通过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
我们也可以可视化检查下:
@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))
本文使用python实现了MCC和MCC的匹配,最后计算出不同指纹的相似度。
Charles@Shenzhen, 20210304,夜
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。