本项目提供了三种掌纹图像预处理和脉络提取方法,用于从掌纹图像中提取清晰的脉络特征。
本项目包含三个Python脚本:
- palmprint_preprocessing.py - 基础掌纹预处理方法
- row_column_histogram_vein_extraction.py - 基于行列直方图的动态二值化方法
- palmprint_preprocessing2.py - 基于Gabor滤波和脊线检测的综合脉络提取方法
三种方法都支持批量处理,能够自动处理指定文件夹中的所有图像文件。
该方法采用传统的图像处理技术进行掌纹预处理,主要包括以下步骤:
使用CLAHE(对比度受限的自适应直方图均衡化)处理图像:
- 将图像分成8×8的小块
- 在每个小块内进行直方图均衡化
- 限制对比度增强幅度,避免噪声放大
- 适应不同光照条件
应用快速非局部均值去噪算法:
- 通过搜索相似图像块进行去噪
- 保留边缘细节
- 参数:h=10, templateWindowSize=7, searchWindowSize=21
使用形态学黑帽操作:
- 提取比周围区域暗的特征(掌纹脉络)
- 将提取的特征叠加到原图上
- 增强脉络的可见性
通过形态学开运算和闭运算:
- 开运算(先腐蚀后膨胀):去除细小噪声和细小分支
- 闭运算(先膨胀后腐蚀):连接断裂的脉络,填充孔洞
- 保留主要的主干脉络
使用高斯自适应阈值方法:
- 不是使用全局阈值,而是为每个像素点计算局部阈值
- 使用11×11的邻域窗口
- 通过高斯加权计算局部均值
- 阈值 = 局部均值 - 2
原始图像 → 灰度转换 → CLAHE增强 → 去噪 → 黑帽增强 → 形态学提取 → 自适应阈值 → 输出
*_enhanced.jpg- 增强后的掌纹图像*_binary.jpg- 二值化处理后的图像*_structure.jpg- 提取的主干结构图像
该方法利用掌纹脉络在图像中的分布特性(脉络线条在每行和每列中占比较小),通过行列直方图分析进行动态二值化。
与方法一相同,使用CLAHE和快速非局部均值去噪。
简单方法:
- 对每一列像素计算直方图
- 统计累积分布,找到使黑色像素比例达到15%的灰度值作为阈值
- 将该列中灰度值≤阈值的像素设为黑色(脉络)
自适应窗口方法:(建议采用这种方法)
- 以当前列为中心,取前后各5列(共11列)作为窗口
- 对窗口内所有像素计算直方图
- 根据窗口统计确定阈值
- 用窗口阈值处理当前列
- 提高统计稳定性,平滑阈值变化
与列处理完全相同,只是方向改为水平方向:
- 对每一行像素进行直方图分析
- 动态确定阈值(黑色像素比例为10%)
- 自适应窗口方法使用11行的窗口
使用逻辑或(OR)操作合并两个二值化结果:
- 只要列二值化或行二值化中任一判断为黑色,合并结果就是黑色
- 更全面地提取脉络特征,避免遗漏
使用3×3椭圆结构元素进行开运算:
- 去除细小噪声
- 保持主干脉络的完整性
将二值化的脉络转换为单像素宽的骨架:
- 优先使用OpenCV的Zhang-Suen算法(cv2.ximgproc.thinning)
- 如果不可用,自动回退到形态学方法
- 提取脉络的中心线,便于特征提取和匹配
将骨架以绿色覆盖到原始图像上:
- 直观显示提取的脉络在原始图像中的位置
- 便于验证提取效果
核心思想: 用局部窗口的统计信息代替单列/单行的统计信息,在保持局部适应性的同时提高统计稳定性。
实现方式:
window_size = 11
start_col = max(0, col - window_size // 2)
end_col = min(width, col + window_size // 2 + 1)
window_pixels = image[:, start_col:end_col]作用:
- 提高统计稳定性:窗口包含11列,像素数量增加11倍
- 平滑局部光照变化:平均邻近列的光照信息
- 抗噪声干扰:噪声的影响被稀释
- 保持局部适应性:窗口仍只覆盖局部区域
原始图像 → 增强去噪 → 列方向动态二值化 → 行方向动态二值化 → 合并结果 → 形态学清理 → 骨架化 → 覆盖到原图
*_denoised.jpg- 增强和去噪后的灰度图像*_binary_col_adaptive.jpg- 基于列直方图的二值化结果*_binary_row_adaptive.jpg- 基于行直方图的二值化结果*_binary_merged_adaptive.jpg- 行和列二值化结果的合并*_cleaned_adaptive.jpg- 形态学清理后的脉络图像*_skeleton_adaptive.jpg- 骨架化后的脉络(单像素宽)*_overlay_adaptive.jpg- 骨架覆盖到原始图像上的结果(绿色显示)
该方法采用多种图像处理技术的组合,通过Gabor滤波器和脊线检测相结合的方式提取掌纹脉络。
使用CLAHE(对比度受限的自适应直方图均衡化)处理图像:
- 将图像分成8×8的小块
- 在每个小块内进行直方图均衡化
- 限制对比度增强幅度,避免噪声放大
- 适应不同光照条件
采用两级降噪策略:
- 高斯模糊降噪:使用5×5高斯核进行初步降噪
- 非局部均值去噪:对保留细节效果更好
- 参数:h=10, templateWindowSize=7, searchWindowSize=21
- 通过搜索相似图像块进行去噪
- 保留边缘细节
使用形态学顶帽和黑帽变换组合增强:
- 顶帽变换(MORPH_TOPHAT):提取比周围区域亮的特征
- 黑帽变换(MORPH_BLACKHAT):提取比周围区域暗的特征(掌纹脉络)
- 组合增强:将顶帽结果叠加到原图,减去黑帽结果
- 增强脉络的可见性和对比度
使用多方向Gabor滤波器提取脉络:
- Gabor滤波器参数:
- ksize=31:滤波器核大小
- sigma=5.0:高斯标准差
- lambd=10.0:正弦波长
- gamma=0.5:空间纵横比
- psi=0:相位偏移
- 多方向处理:0°、45°、90°、135°四个方向
- 最大响应融合:取所有方向的最大响应作为最终结果
- 适应不同方向的脉络特征
使用Sobel算子检测边缘和脊线:
- Sobel算子:计算图像梯度
- sobelx:水平方向梯度
- sobely:垂直方向梯度
- 梯度幅值计算:sqrt(sobelx² + sobely²)
- 归一化处理:将梯度幅值映射到0-255范围
- 检测脉络的边缘和脊线特征
将Gabor滤波和脊线检测结果进行加权融合:
- 加权融合:cv2.addWeighted(gabor_result, 0.5, ridge_result, 0.5, 0)
- 优势互补:
- Gabor滤波:对特定方向的脉络响应强
- 脊线检测:对边缘和梯度变化敏感
- 综合效果:结合两种方法的优势,提高提取准确性
通过形态学操作优化最终结果:
- 二值化:使用Otsu方法自动确定阈值
- 闭运算:连接断裂的脉络,使用3×3椭圆结构元素,迭代2次
- 开运算:去除小噪点,使用2×2椭圆结构元素,迭代1次
- 骨架化:使用迭代腐蚀方法提取单像素宽的骨架
- 提取脉络的中心线
- 便于特征提取和匹配
原始图像 → 灰度转换 → CLAHE增强 → 多级降噪 → 形态学增强 → Gabor滤波 → 脊线检测 → 结果融合 → 形态学处理 → 骨架化 → 输出
*_veins.png- 最终提取的掌纹脉络图像(骨架化结果)*_process.png- 处理过程可视化图像(包含7个子图)
该方法提供完整的处理过程可视化,包含7个子图:
- 原始图像
- 预处理结果
- 降噪结果
- 增强结果
- Gabor滤波结果
- 脊线检测结果
- 融合结果
- 最终脉络
- Python 3.7 或更高版本
- opencv-python
- numpy
-
准备数据
- 将掌纹图像放入
data文件夹 - 支持的格式:.jpg, .jpeg, .png, .bmp, .tiff
- 将掌纹图像放入
-
运行脚本
python palmprint_preprocessing.py
-
查看结果
- 处理结果保存在
output文件夹 - 每个输入图像生成3个输出文件
- 处理结果保存在
-
准备数据
- 将掌纹图像放入
data文件夹 - 支持的格式:.jpg, .jpeg, .png, .bmp, .tiff
- 将掌纹图像放入
-
运行脚本
python row_column_histogram_vein_extraction.py
-
查看结果
- 处理结果保存在
output_row_column_histogram文件夹 - 每个输入图像生成7个输出文件
- 处理结果保存在
-
准备数据
- 将掌纹图像放入
data文件夹 - 支持的格式:.jpg, .jpeg, .png, .bmp, .tiff
- 将掌纹图像放入
-
运行脚本
python palmprint_preprocessing2.py
-
查看结果
- 处理结果保存在
output_palmprint2文件夹 - 每个输入图像生成2个输出文件:
*_veins.png- 最终提取的掌纹脉络图像*_process.png- 处理过程可视化图像
- 处理结果保存在
在 palmprint_preprocessing.py 中可以调整的参数:
# CLAHE参数
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
# clipLimit: 对比度限制(默认2.0)
# tileGridSize: 网格大小(默认8×8)
# 去噪参数
cv2.fastNlMeansDenoising(enhanced, None, h=10, templateWindowSize=7, searchWindowSize=21)
# h: 去噪强度(默认10)
# templateWindowSize: 模板窗口大小(默认7)
# searchWindowSize: 搜索窗口大小(默认21)
# 形态学参数
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
# 结构元素大小(默认5×5)
# 自适应阈值参数
cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
# blockSize: 邻域窗口大小(默认11)
# C: 常数(默认2)在 row_column_histogram_vein_extraction.py 中可以调整的参数:
# 列方向黑色像素比例阈值
binary_col = adaptive_dynamic_threshold_by_column(denoised, black_ratio_threshold=0.15, window_size=11)
# black_ratio_threshold: 黑色像素比例(默认0.15,即15%)
# window_size: 自适应窗口大小(默认11)
# 行方向黑色像素比例阈值
binary_row = adaptive_dynamic_threshold_by_row(denoised, black_ratio_threshold=0.1, window_size=11)
# black_ratio_threshold: 黑色像素比例(默认0.1,即10%)
# window_size: 自适应窗口大小(默认11)
# 形态学清理参数
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
# 结构元素大小(默认3×3)
# 骨架覆盖颜色
overlay = overlay_skeleton_on_image(image, skeleton, color=(0, 255, 0))
# color: BGR颜色值(默认绿色:(0, 255, 0))在 palmprint_preprocessing2.py 中可以调整的参数:
# CLAHE参数
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
# clipLimit: 对比度限制(默认2.0)
# tileGridSize: 网格大小(默认8×8)
# 高斯模糊参数
denoised = cv2.GaussianBlur(image, (5, 5), 0)
# kernel_size: 高斯核大小(默认5×5)
# 非局部均值去噪参数
cv2.fastNlMeansDenoising(denoised, None, h=10, templateWindowSize=7, searchWindowSize=21)
# h: 去噪强度(默认10)
# templateWindowSize: 模板窗口大小(默认7)
# searchWindowSize: 搜索窗口大小(默认21)
# 形态学增强参数
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
# 结构元素大小(默认15×15)
# Gabor滤波器参数
ksize = 31 # 滤波器核大小
sigma = 5.0 # 高斯标准差
lambd = 10.0 # 正弦波长
gamma = 0.5 # 空间纵横比
psi = 0 # 相位偏移
angles = [0, 45, 90, 135] # 滤波方向
# Sobel算子参数
ksize = 3 # Sobel核大小(默认3)
# 结果融合参数
cv2.addWeighted(gabor_result, 0.5, ridge_result, 0.5, 0)
# alpha: Gabor结果权重(默认0.5)
# beta: 脊线结果权重(默认0.5)
# 形态学处理参数
kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
kernel_open = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2))
# 闭运算:结构元素大小(默认3×3),迭代次数(默认2)
# 开运算:结构元素大小(默认2×2),迭代次数(默认1)黑色像素比例阈值:
- 较小值(0.05-0.10):更严格,只提取最暗的脉络,减少误检
- 中等值(0.10-0.15):平衡,适合大多数情况
- 较大值(0.15-0.20):宽松,提取更多细节,可能包含噪声
自适应窗口大小:
- window_size = 1:等价于简单方法
- window_size = 11:平衡局部性和稳定性(推荐)
- window_size = 21:更稳定,但可能过度平滑
- window_size = 51:接近全局阈值,失去局部适应性
| 特性 | 方法一 | 方法二 | 方法三 |
|---|---|---|---|
| 核心思想 | 传统图像处理技术 | 行列直方图动态分析 | Gabor滤波+脊线检测 |
| 二值化方法 | 全局自适应阈值 | 动态阈值(基于直方图) | Otsu自动阈值 |
| 适应性 | 局部自适应 | 双向自适应(行+列) | 多方向自适应 |
| 输出文件数 | 3个 | 7个 | 2个 |
| 骨架化 | 无 | 有 | 有 |
| 可视化 | 有 | 骨架覆盖 | 完整过程可视化 |
| 适用场景 | 快速预处理 | 精确脉络提取 | 高精度脉络提取 |
在脚本的主函数部分修改:
data_directory = "data" # 输入目录
output_directory = "output" # 输出目录- 方法一:适合快速预处理,需要简单的脉络提取
- 方法二:适合精确脉络提取,需要骨架化结果
- 方法三:适合高精度脉络提取,需要完整过程可视化
- 减小图像尺寸
- 减小自适应窗口大小
- 使用简单方法而非自适应方法
- 调整黑色像素比例阈值
- 调整自适应窗口大小
- 检查图像质量和光照条件
找到 6 个图像文件
开始批量处理...
--------------------------------------------------
处理完成: 1
- 增强图像: output\1_enhanced.jpg
- 二值化图像: output\1_binary.jpg
- 主干结构: output\1_structure.jpg
--------------------------------------------------
批量处理完成!共处理 6 个图像
结果保存在: output
基于行和列直方图的动态二值化掌纹脉络提取
==================================================
找到 6 个图像文件
使用方法: adaptive
开始批量处理...
--------------------------------------------------
处理完成: 1 (方法: adaptive)
- 去噪图像: output_row_column_histogram\1_denoised.jpg
- 列二值化图像: output_row_column_histogram\1_binary_col_adaptive.jpg
- 行二值化图像: output_row_column_histogram\1_binary_row_adaptive.jpg
- 合并二值化图像: output_row_column_histogram\1_binary_merged_adaptive.jpg
- 清理后图像: output_row_column_histogram\1_cleaned_adaptive.jpg
- 骨架图像: output_row_column_histogram\1_skeleton_adaptive.jpg
- 覆盖图像: output_row_column_histogram\1_overlay_adaptive.jpg
--------------------------------------------------
批量处理完成!共处理 6 个图像
结果保存在: output_row_column_histogram
基于Gabor滤波和脊线检测的综合脉络提取
==================================================
找到 6 个图像文件
开始批量处理...
--------------------------------------------------
处理完成: 1
- 脉络图像: output_palmprint2\1_veins.png
- 处理过程: output_palmprint2\1_process.png
--------------------------------------------------
批量处理完成!共处理 6 个图像
结果保存在: output_palmprint2
本项目仅供学习和研究使用。
如有问题或建议,欢迎提出Issue。


