3. 指纹图像增强
任务说明
本案例针对采集质量不佳的指纹图像(存在噪声、脊线断裂或对比度不足),使用Gabor滤波结合方向场估计实现指纹图像增强,修复脊线断裂并抑制噪声,为后续特征提取提供更清晰的输入。输入为灰度指纹图像,输出为增强后的二值化脊线图。
实现方案
增强流程分为四个步骤:(1)归一化——调整灰度均值和方差;(2)方向场估计——通过Sobel梯度计算每个像素所在脊线的局部方向;(3)Gabor滤波——沿脊线方向进行带通滤波,连接断裂脊线并去噪;(4)自适应二值化——将增强结果转为清晰的脊线/谷线二值图。核心参数(Gabor频率、方向数、滤波器尺寸)在代码中显式定义,可直接运行验证。
代码实现
import cv2
import numpy as np
import math
def normalize(img, mean_target=100.0, var_target=100.0):
"""灰度归一化到指定均值和方差"""
mean = img.mean()
var = img.var()
normalized = (img - mean) * math.sqrt(var_target / (var + 1e-6)) + mean_target
return np.clip(normalized, 0, 255).astype(np.uint8)
def estimate_orientation(img, block_size=16):
"""基于梯度计算方向场(每个block一个方向角,弧度)"""
gx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
gy = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
rows, cols = img.shape
orientation = np.zeros((rows // block_size, cols // block_size), dtype=np.float32)
for i in range(0, rows - block_size, block_size):
for j in range(0, cols - block_size, block_size):
Vx = (2 * gx[i:i+block_size, j:j+block_size] * gy[i:i+block_size, j:j+block_size]).sum()
Vy = (gx[i:i+block_size, j:j+block_size]**2 - gy[i:i+block_size, j:j+block_size]**2).sum()
angle = 0.5 * math.atan2(Vx, Vy) # 主方向
orientation[i // block_size, j // block_size] = angle
return orientation
def gabor_filter_block(block, angle, freq=0.1, ksize=7, sigma=2.0):
"""对单个block应用Gabor滤波(沿方向angle增强脊线)"""
theta = angle + math.pi / 2 # Gabor核垂直于脊线方向
kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, 1.0/freq, 0.5, 0)
return cv2.filter2D(block, cv2.CV_64F, kernel)
def enhance_fingerprint(img, block_size=16):
"""完整增强流程:归一化→方向场→Gabor滤波→二值化"""
img = normalize(img)
orientation = estimate_orientation(img, block_size)
enhanced = np.zeros_like(img, dtype=np.float32)
rows, cols = img.shape
for i in range(0, rows - block_size, block_size):
for j in range(0, cols - block_size, block_size):
block = img[i:i+block_size, j:j+block_size].astype(np.float32)
angle = orientation[i // block_size, j // block_size]
filtered = gabor_filter_block(block, angle)
enhanced[i:i+block_size, j:j+block_size] = filtered
# 自适应二值化(Otsu)
enhanced_u8 = np.clip(enhanced, 0, 255).astype(np.uint8)
_, binary = cv2.threshold(enhanced_u8, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
return binary
# 使用示例(输入为灰度指纹图像,路径自行替换)
if __name__ == "__main__":
img = cv2.imread("fingerprint.png", cv2.IMREAD_GRAYSCALE)
if img is None:
print("请提供有效的指纹图像路径")
else:
result = enhance_fingerprint(img)
cv2.imwrite("enhanced_fingerprint.png", result)
print("增强完成,结果已保存为 enhanced_fingerprint.png")
关键参数说明
- block_size=16:方向场估计的局部窗口大小,与指纹脊线周期(约8~12像素)匹配;
- freq=0.1:Gabor核的脊线频率(周期为10像素),可根据实际图像调整;
- ksize=7, sigma=2.0:滤波器尺寸与高斯包络标准差,控制增强的平滑程度。
验证方法
准备一张含噪声或脊线断裂的指纹灰度图(如FVC2002数据库样本),运行上述代码。判定标准:
- 程序正常输出
enhanced_fingerprint.png,无异常报错; - 目视检查输出图像:脊线连续完整,断裂处被连接,背景噪声明显减少;
- 与输入图像对比,脊线/谷线对比度增强,二值化后无大面积黑色空洞或白色粘连。
判定标准
运行代码后,若输出图像满足:脊线断裂处被有效连接、背景噪声明显减少、脊线宽度均匀且无大面积伪连接,则判定增强成功。若效果不理想,优先调整freq(脊线周期)和block_size(方向场窗口)两个参数。