4. 指纹图像二值化

任务说明

本案例将上一阶段增强处理后的指纹灰度图像转换为二值图像,使脊线(纹线凸起部分)与谷线(纹线间凹陷部分)分离为黑白两色,为后续细化和特征提取提供清晰的输入。输入为8位灰度指纹图像,输出为单通道二值图像(0或255)。

实现方案

采用全局阈值与局部自适应阈值相结合的策略:先使用Otsu方法计算全局最优阈值,再对图像分块计算局部均值,通过加权融合得到每个像素的最终阈值,从而兼顾光照不均和脊线粗细变化的影响。核心处理流程如下:

  1. 读取灰度指纹图像;
  2. 使用Otsu算法计算全局阈值;
  3. 将图像划分为16×16像素的块,计算每块均值作为局部阈值;
  4. 对每个像素,将全局阈值与所在块局部阈值按权重0.5:0.5融合,得到自适应阈值;
  5. 像素值大于等于阈值置255(脊线),否则置0(谷线)。
灰度指纹图像 8-bit, 256×256 Otsu全局阈值 T_global 分块局部均值 T_local (16×16块) 阈值融合 T = 0.5·T_global + 0.5·T_local 二值图像 0 或 255 逐像素比较 ≥T → 255(脊线) / <T → 0(谷线)

代码实现


import cv2
import numpy as np

def adaptive_binarize(image_path, block_size=16, weight_global=0.5):
    """
    指纹图像自适应二值化
    :param image_path: 输入灰度图像路径
    :param block_size: 局部块大小(像素)
    :param weight_global: 全局阈值权重,局部阈值权重 = 1 - weight_global
    :return: 二值图像 (0和255)
    """
    # 读取灰度图
    img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    if img is None:
        raise ValueError(f"无法读取图像: {image_path}")

    # 1. Otsu全局阈值
    _, t_global = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 分块局部均值
    h, w = img.shape
    t_local = np.zeros_like(img, dtype=np.float32)

    for y in range(0, h, block_size):
        for x in range(0, w, block_size):
            block = img[y:y+block_size, x:x+block_size]
            block_mean = np.mean(block)
            t_local[y:y+block_size, x:x+block_size] = block_mean

    # 3. 阈值融合
    weight_local = 1.0 - weight_global
    threshold_map = weight_global * t_global + weight_local * t_local

    # 4. 像素比较生成二值图
    binary = np.where(img >= threshold_map, 255, 0).astype(np.uint8)

    return binary

if __name__ == "__main__":
    # 输入增强后的指纹图像(示例路径,请替换为实际文件)
    input_path = "enhanced_fingerprint.png"
    output_path = "binary_fingerprint.png"

    result = adaptive_binarize(input_path, block_size=16, weight_global=0.5)
    cv2.imwrite(output_path, result)
    print(f"二值化完成,结果已保存至: {output_path}")

落地与验证

运行环境:Python 3.8+,需安装OpenCV(pip install opencv-python numpy)。

执行方式:将增强后的指纹图像命名为enhanced_fingerprint.png放在脚本同目录,运行python binarize.py,输出文件为binary_fingerprint.png。

验证方法:用图像查看工具打开输出图像,观察脊线是否呈现为连续白色纹路、谷线为黑色背景。可通过以下客观指标辅助判定:

  • 计算二值图像中白色像素占比,正常指纹脊线占比约30%~45%;
  • 沿垂直于脊线方向取一条像素剖面,应观察到黑白交替的方波模式,且脊线宽度(白色连续段)在5~15像素范围内;
  • 若图像中出现大面积全黑或全白区域,或脊线断裂严重,可调整block_size(8~32)或weight_global(0.3~0.7)后重新运行。

判定标准:输出图像中脊线连续、谷线清晰分离,无大面积噪声块,且上述占比与剖面检查符合指纹形态特征,即视为通过。