2. 指纹图像分割
任务说明
本案例处理一张包含背景噪声的指纹灰度图像,目标是将有效指纹区域(脊线与谷线所在的皮肤区域)与背景分离,生成二值掩膜,并去除图像四角及边缘的无效区域。输入为单张8位灰度指纹图像,输出为与输入同尺寸的掩膜图像(有效区域为白色,背景为黑色),以及应用掩膜后的分割结果图像。
实现方案
采用局部灰度方差与形态学后处理相结合的方法:指纹脊谷交替结构在局部窗口内产生较高灰度方差,而平滑背景区域方差较低。通过自适应阈值分割方差图得到初始掩膜,再使用开运算去除孤立噪点、闭运算填充孔洞,最终保留最大连通域作为有效指纹区域。
代码实现
import cv2
import numpy as np
def segment_fingerprint(image_path, output_mask_path, output_result_path):
"""
指纹图像分割:将有效指纹区域与背景分离。
参数:
image_path: 输入灰度指纹图像路径
output_mask_path: 输出二值掩膜保存路径
output_result_path: 输出分割结果保存路径
"""
# 1. 读取图像(强制灰度)
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
if img is None:
raise ValueError(f"无法读取图像: {image_path}")
# 2. 计算局部灰度方差(15×15窗口)
mean = cv2.blur(img, (15, 15))
sqr_mean = cv2.blur(img.astype(np.float32) ** 2, (15, 15))
variance = sqr_mean - mean.astype(np.float32) ** 2
variance = np.clip(variance, 0, None).astype(np.uint8)
# 3. Otsu自适应阈值分割方差图
_, initial_mask = cv2.threshold(variance, 0, 255,
cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 4. 形态学后处理
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
opened = cv2.morphologyEx(initial_mask, cv2.MORPH_OPEN, kernel) # 去除孤立噪点
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel) # 填充内部孔洞
# 5. 保留最大连通域(去除边缘残留背景块)
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(closed, 8)
if num_labels <= 1:
final_mask = np.zeros_like(closed)
else:
# 排除背景标签0,取面积最大的连通域
largest_label = 1 + np.argmax(stats[1:, cv2.CC_STAT_AREA])
final_mask = np.where(labels == largest_label, 255, 0).astype(np.uint8)
# 6. 应用掩膜得到分割结果
result = cv2.bitwise_and(img, final_mask)
# 7. 保存输出
cv2.imwrite(output_mask_path, final_mask)
cv2.imwrite(output_result_path, result)
return final_mask, result
if __name__ == "__main__":
# 示例调用(请替换为实际文件路径)
mask, seg = segment_fingerprint(
"fingerprint.png",
"fingerprint_mask.png",
"fingerprint_segmented.png"
)
print("分割完成,掩膜尺寸:", mask.shape)
依赖与运行
需要安装 opencv-python 与 numpy:
pip install opencv-python numpy
将待处理的指纹灰度图像命名为 fingerprint.png 放在脚本同目录,运行后生成 fingerprint_mask.png(二值掩膜)与 fingerprint_segmented.png(分割结果)。
验证方法
运行脚本后,通过以下标准判定分割是否成功:
- 掩膜合理性:
fingerprint_mask.png中白色区域应覆盖指纹脊线密集的中央区域,四角与边缘背景为黑色,白色区域内部无明显孔洞,外部无大面积孤立白块。 - 分割准确性:
fingerprint_segmented.png中背景区域像素值全部为0(纯黑),有效指纹区域的脊线纹理保持清晰可辨,未被误删。 - 定量检查:在Python中执行以下代码统计掩膜前景占比,通常指纹有效区域占整幅图像的30%~60%为合理范围:
import cv2
mask = cv2.imread("fingerprint_mask.png", cv2.IMREAD_GRAYSCALE)
foreground_ratio = (mask > 0).sum() / mask.size
print(f"有效区域占比: {foreground_ratio:.2%}")
若前景占比明显偏离该范围(如低于10%或高于90%),说明阈值或形态学参数不适配当前图像,可调整窗口大小(15改为11或21)或核对输入图像是否为包含大面积背景的指纹图。