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数据库样本),运行上述代码。判定标准:

  1. 程序正常输出enhanced_fingerprint.png,无异常报错;
  2. 目视检查输出图像:脊线连续完整,断裂处被连接,背景噪声明显减少;
  3. 与输入图像对比,脊线/谷线对比度增强,二值化后无大面积黑色空洞或白色粘连。
指纹图像增强处理流程与验证观测点 原始指纹图像 含噪声/断裂 灰度归一化 均值/方差调整 方向场估计 Sobel梯度→主方向 Gabor滤波增强 沿脊线方向带通 二值化输出 脊线/谷线分离 验证观测点 脊线断裂处是否被连接 背景噪声是否被抑制 脊线/谷线对比度是否增强 二值化后有无大面积空洞/粘连

判定标准

运行代码后,若输出图像满足:脊线断裂处被有效连接、背景噪声明显减少、脊线宽度均匀且无大面积伪连接,则判定增强成功。若效果不理想,优先调整freq(脊线周期)和block_size(方向场窗口)两个参数。