import cv2
import numpy as np
# 读取第一张指纹图像
zhiwen1 = cv2.imread('zw1.png')
# 定义2×2的结构元素(形态学运算的"工具",uint8类型)
kernel = np.ones((2,2),np.uint8)
- 结构元素(kernel) :形态学运算的核心工具,类似滤波中的 "核",决定了运算的范围和强度。这里用
np.ones()
创建全 1 矩阵,尺寸越大,运算效果越明显(后续闭运算用了 4×4 的核)。
开运算(cv2.MORPH_OPEN
):去除图像中的小噪点
# 对zhiwen1执行开运算
zhiwen1_new = cv2.morphologyEx(zhiwen1, cv2.MORPH_OPEN, kernel)
- 原理 :开运算 = 先腐蚀(Erode)后膨胀(Dilate)
- 腐蚀:消除图像中的细小噪声和突出的小区域(让前景物体 "收缩");
- 膨胀:在腐蚀的基础上恢复前景物体的原有大小(但噪声已被消除)。
- 效果 :
能有效去除图像中的孤立小噪点、细小白点或毛刺,同时基本保持前景物体的整体形状和尺寸不变。适合处理指纹图像中可能存在的杂点干扰。 - 参数 :
kernel
为 2×2,说明运算范围较小,适合去除细微噪声。
闭运算(cv2.MORPH_CLOSE
):填补图像中的小孔洞
# 读取第二张指纹图像
zhiwen2 = cv2.imread('zw2.png')
# 定义4×4的结构元素(更大的核,处理更明显的孔洞)
kernel = np.ones((4,4),np.uint8)
# 对zhiwen2执行闭运算
zhiwen2_new = cv2.morphologyEx(zhiwen2, cv2.MORPH_CLOSE, kernel)
原理:闭运算 = 先膨胀(Dilate)后腐蚀(Erode)
- 膨胀:填充前景物体中的小孔洞和凹陷(让前景物体 "扩张");
- 腐蚀:在膨胀的基础上恢复前景物体的原有大小(但孔洞已被填补)
- 效果 :
主要用于填补图像中前景物体内部的小孔洞、裂缝或凹陷,使物体轮廓更完整。这里用 4×4 的核,说明目标孔洞较大,需要更强的填充效果。 - 对比开运算:开运算针对 "外部噪声",闭运算针对 "内部孔洞"。
梯度运算(cv2.MORPH_GRADIENT
):提取物体边缘
# 重新读取第一张指纹图像
zhiwen1 = cv2.imread('zw1.png')
# 先单独演示膨胀和腐蚀(辅助理解梯度运算)
pz_zhiwen1 = cv2.dilate(zhiwen1, kernel, iterations=1) # 膨胀:前景物体扩大
fs_zhiwen1 = cv2.erode(zhiwen1, kernel, iterations=1) # 腐蚀:前景物体缩小
# 执行梯度运算
td_zhiwen1 = cv2.morphologyEx(zhiwen1, cv2.MORPH_GRADIENT, kernel)
- 原理 :梯度运算 = 膨胀结果 - 腐蚀结果
膨胀会使物体边缘 "外扩",腐蚀会使物体边缘 "内缩",两者的差值恰好是物体的边缘轮廓。 - 效果 :
能提取前景物体的边缘信息,得到物体的轮廓线。对于指纹图像,可突出指纹的纹路边缘,便于后续的特征提取(如指纹的脊线和谷线)。 - 单独显示膨胀和腐蚀 :代码中先展示了
pz_zhiwen1
(膨胀)和fs_zhiwen1
(腐蚀)的效果,帮助理解梯度运算的来源。
Sobel 算子:检测水平 / 垂直方向边缘
Sobel 算子通过计算图像梯度来检测边缘,可分别检测水平、垂直或对角线方向的边缘,代码中主要展示水平(x 方向)和垂直(y 方向)检测:
基础 Sobel 运算(存在缺陷)
# dx=1, dy=0 表示检测x方向(水平)边缘(梯度变化在水平方向)
yt_x = cv2.Sobel(yt, -1, dx=1, dy=0)
cv2.imshow('yt_x', yt_x)
- 参数说明:
-1
表示输出图像与输入图像深度相同(通常为uint8
);dx
和dy
分别表示 x 和 y 方向的导数阶数(1 表示一阶导数)。 - 缺陷:
uint8
类型只能表示 0-255 的正数,而边缘梯度可能为负(如从亮到暗的过渡),负数会被截断为 0,导致部分边缘丢失。
改进:使用cv2.CV_64F
保留正负梯度
# 使用64位浮点数(cv2.CV_64F)存储结果,可保留负数
yt_x_64 = cv2.Sobel(yt, cv2.CV_64F, dx=1, dy=0)
# 转换为绝对值后再转为uint8,恢复所有边缘(包括负梯度对应的边缘)
yt_x_full = cv2.convertScaleAbs(yt_x_64)
cv2.imshow('yt_x_full', yt_x_full)
- 关键:
cv2.CV_64F
支持负数存储,cv2.convertScaleAbs()
通过取绝对值 + 类型转换,完整保留正负梯度对应的边缘(如亮→暗和暗→亮的过渡都能检测到)。