指纹识别和验证是最古老,最流行和广泛使用的生物特征技术。众所周知,每个人都有独特且不变的指纹,指纹是指尖表面上的凸起 (ridges
,也称脊线)和凹陷 (valleys
,也称谷线)的模式图案。由于大多数自动指纹识别系统都是基于被称为细节 (minutiae
) 的局部凸起特征,准确地标记细节并拒绝虚假的标记非常重要。但是,由于皮肤和印模条件的变化,指纹图像质量下降和损坏。因此,需要在细节提取之前采用图像增强技术。自动指纹匹配的关键步骤是从输入指纹图像中可靠地提取细节。
在本节中,我们将首先使用带有噪声的二值指纹图像利用数学形态操作来实现指纹增强技术。然后,我们将介绍如何从预处理的指纹图像中提取细节。
形态图像处理是指与图像特征形状(即形态学)相关的一组非线性操作的应用。这些操作特别适合处理二值图像,在二值图像中像素表示为 0
(背景,黑色) 或 1
(前景,白色)。
在形态学操作中,使用一个小模板图像的结构元素 (structuring element
, SE
) 来检测输入图像中的所有可能位置,然后,算法使用集合算子将其与对应像素的邻域进行比较。形态操作测试 SE
是否与相应的邻域相匹配,或者是否与之相交。我们使用 scikit-Image.Morphology
和 Scipy.BDimage
模块的形态学函数来增强指纹图像,所采用的形态学操作如下:
基本形态学操作:
组合形态学操作:
其中 A A A 表示二值图像, B B B 表示结构元素,形态学的开运算和闭运算可以顺序地用于从二值图像中去除噪声(小前景对象),可以将其用于指纹图像增强的预处理步骤。
在本节中,我们将从带有噪声的指纹图像开始,然后使用二值形态学算子(例如开运算、闭运算和骨架化)增强图像,指纹增强函数在实际应用中更加复杂,其中涉及到图像处理中的许多步骤,在本节中,我们旨在介绍基本的指纹增强技术。
(1) 首先导入所需的库和模块:
from skimage.io import imread
from skimage.color import rgb2gray
import numpy as np
import matplotlib.pylab as plt
from skimage.morphology import binary_opening, binary_closing, skeletonize, square
from scipy.ndimage import morphological_gradient
from skimage.filters import threshold_otsu
def plot_image(image, title=None, sz=10):
plt.imshow(image)
plt.title(title, size=sz)
plt.axis('off')
(2) 首先,使用阈值技术将灰度输入图像转换为二值图像,使用固定阈值 0.5
来对图像进行二值化处理(我们也可以使用 OTSU
等最佳阈值算法来自动获得阈值)。在形态学闭运算之后执行开运算可以在带有噪声的二值指纹输入图像中去除小前景对象,即噪声对象。使用骨架化和形态学梯度,可以进一步增强输出图像:
im = rgb2gray(imread('fingerprint.jpg'))
im[im <= 0.5] = 0 # binarize
im[im > 0.5] = 1
im_o = binary_opening(im, square(2))
im_c = binary_closing(im, square(2))
im_oc = binary_closing(binary_opening(im, square(2)), square(3))
im_s = skeletonize(im_oc)
im_g = morphological_gradient(im_oc.astype(np.uint8), size=(2,2))
plt.imsave('fingerprint_input.jpg', im_s, cmap='gray')
(3) 绘制二值输入噪声图像以及通过对输入应用单个或一系列形态学操作获得的增强输出图像:
plt.figure(figsize=(20,12))
plt.gray()
plt.subplot(231), plot_image(im, 'original')
plt.subplot(232), plot_image(im_o, 'opening')
plt.subplot(233), plot_image(im_c, 'closing')
plt.subplot(234), plot_image(im_oc, 'opening + closing')
plt.subplot(235), plot_image(im_s, 'skeletonizing')
plt.subplot(236), plot_image(im_g, 'morphological gradient')
plt.show()
由于其独特性、紧凑性和兼容性,基于细节的表示已成为最广泛采用的指纹表示方案。指纹的独特性仅由局部凸起特征及其关系决定。指纹交替的凸起和凹陷,沿恒定的局部方向流动。两个最突出的局部凸起特征如下:
Ridge ending
)Ridge bifurcation
)凸起终点定义为凸起突然结束的点,而凸起分叉定义为凸起分叉或分叉成分枝凸起的点,这些特征统称为细节 (minutiae
)。细节模板即使被泄漏也并不会导致严重后果,因为根据细节重建灰度图像十分困难。
大多数指纹提取和匹配技术都将特征集限制在两种类型的细节上,即凸起终点和凸起分叉。高质量的指纹通常包含约 40-100
个细节,每个细节的凸起终点和凸起分叉类型都有三个属性,即细节点类型、细节点坐标和局部凸起方向
θ
θ
θ。给定指纹的细节表示,将指纹与数据库进行匹配可以表示为点匹配的问题。匹配问题可以定义为计算查询和参考指纹特征集之间的匹配程度。
在本节中,我们将学习如何从增强的指纹图像中提取凸起终点和凸起分叉特征(即细节)。在本节中,我们将指纹凸起部分表示为黑色线条而非白色线条。
(1) 导入所需的库和模块,实现函数 minutiae_at()
,该函数获取二值指纹图像的像素和图像内的坐标
(
i
,
j
)
(i,j)
(i,j),并检查该位置的像素的细节类型(凸起终点或凸起分叉):
from PIL import Image, ImageDraw
from skimage.io import imread
from skimage.color import rgb2gray
import numpy as np
import matplotlib.pylab as plt
from skimage.morphology import binary_opening, binary_closing, skeletonize, square
from scipy.ndimage import morphological_gradient
from skimage.filters import threshold_otsu
def plot_image(image, title=None, sz=10):
plt.imshow(image)
plt.title(title, size=sz)
plt.axis('off')
cells = [(-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1)]
def minutiae_at(pixels, i, j):
values = [pixels[i + k][j + l] for k, l in cells]
crossings = 0
for k in range(0, 8):
crossings += abs(values[k] - values[k + 1])
crossings /= 2
if pixels[i][j] == 1:
if crossings == 1:
return "ending"
if crossings == 3:
return "bifurcation"
return "none"
(2) 接下来,定义函数 calculate_minutiaes()
以从增强的指纹输入图像中提取细节,使用函数 minutiae_at()
来确定凸起终点/分叉像素,并分别用红色和绿色对它们进行着色。该函数期望凸起是白色的,因此需要首先反转输入图像,然后进行二值化:
def calculate_minutiaes(im):
pixels = 255 - np.array(im).T
pixels = 1.0*(pixels > 10)
(x, y) = im.size
result = im.convert("RGB")
draw = ImageDraw.Draw(result)
colors = {"ending" : (150, 0, 0), "bifurcation" : (0, 150, 0)}
ellipse_size = 2
for i in range(1, x - 1):
for j in range(1, y - 1):
minutiae = minutiae_at(pixels, i, j)
if minutiae != "none":
draw.ellipse([(i - ellipse_size, j - ellipse_size), (i + ellipse_size, j + ellipse_size)], outline = colors[minutiae])
del draw
return result
(3) 用提取的细节绘制输入和输出图像:
im = Image.fromarray(255. - np.array(Image.open('fingerprint_input.jpg').convert("L"))) # covert to grayscale
out = calculate_minutiaes(im)
plt.figure(figsize=(15,12))
plt.gray()
plt.subplot(121), plot_image(im, 'input thinned')
plt.subplot(122), plot_image(out, 'with minutiaes extracted')
plt.show()
指纹是人类手指末端指腹上由凹凸的皮肤所形成的纹路,众所周知,指纹具有“各不相同、终生不变”的特性,因此指纹通常可以用于识别人的身份。但是,由于皮肤和印模条件的变化,指纹图像质量会下降和损坏。因此,需要在细节提取之前采用图像增强技术。本节中,我们学习了如何利用形态学操作增强指纹图像,并提取指纹细节。
Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲/逆扭曲
Python图像处理【6】通过哈希查找重复和类似的图像
Python图像处理【7】采样、卷积与离散傅里叶变换
Python图像处理【8】使用低通滤波器模糊图像
Python图像处理【9】使用高通滤波器执行边缘检测
Python图像处理【10】基于离散余弦变换的图像压缩
Python图像处理【11】利用反卷积执行图像去模糊
Python图像处理【12】基于小波变换执行图像去噪
Python图像处理【13】使用PIL执行图像降噪
Python图像处理【14】基于非线性滤波器的图像去噪
Python图像处理【15】基于非锐化掩码锐化图像
Python图像处理【16】OpenCV直方图均衡化