手搓工具之手写签字识别提取工具

项目简介

这是一个基于 Python 和 OpenCV 的手写签名自动提取工具。能够从图片中智能识别签名区域,去除背景,生成透明背景的 PNG 图片。支持单张处理、批量处理和实时摄像头拍照三种模式。


项目GitHub地址

技术架构

核心依赖

  • OpenCV (cv2): 图像处理核心库,负责图像读取、处理和计算机视觉操作
  • NumPy: 数值计算库,用于高效的数组和矩阵运算

项目结构

bash 复制代码
bio-signature/
├── signature_extractor.py      # 核心实现代码
├── demo_signature_test.py      # 测试脚本
├── requirements.txt            # 依赖配置
├── test_images/                # 测试图片目录
└── extracted_signatures/       # 输出目录(自动创建)

核心算法原理

1. 图像预处理(Preprocessing)

目的:将彩色图像转换为便于处理的灰度图,并降噪。

python 复制代码
def preprocess_image(self, image):
    # 步骤1:转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 步骤2:高斯模糊降噪(5x5核)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    
    return blurred

技术要点

  • 灰度化:将 RGB 三通道简化为单通道,减少计算量
  • 高斯模糊:使用 5×5 的高斯核平滑图像,去除小噪点,保留主要结构

2. 二值化处理(Binarization)

目的:将图像转换为黑白二值图,区分前景(签名)和背景。

提供两种模式:

模式A:自适应阈值(推荐)

python 复制代码
binary = cv2.adaptiveThreshold(
    processed, 255,                      # 输入图像,最大值
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,      # 自适应方法:高斯加权
    cv2.THRESH_BINARY_INV,               # 反转二值化
    21,                                  # 邻域大小:21×21
    10                                   # 常数C:阈值调整参数
)

优势:能够自动适应不同光照条件,处理光照不均匀的图片

模式B:固定阈值

python 复制代码
_, binary = cv2.threshold(
    processed, threshold_value, 255,     # 输入图像,阈值,最大值
    cv2.THRESH_BINARY_INV                # 反转二值化
)

适用场景:光照均匀的图片,或需要精确控制效果时

关键技巧

  • 使用 THRESH_BINARY_INV(反转二值化),让签名变成白色(255),背景变成黑色(0)
  • 自适应阈值在每个局部区域计算不同阈值,效果更稳定

3. 形态学操作(Morphological Operations)

目的:去除噪点,平滑签名边缘。

python 复制代码
kernel = np.ones((3, 3), np.uint8)

# 闭运算:先膨胀后腐蚀,填补签名内部的小孔
binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=1)

# 开运算:先腐蚀后膨胀,去除背景中的小噪点
binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=1)

原理解释

  • 闭运算(Close):连接断裂的笔画,填补签名内部的小白点
  • 开运算(Open):消除背景中的小黑点(噪声)
  • 使用 3×3 的结构元素(kernel),进行 1 次迭代

4. 轮廓检测与签名定位(Contour Detection)

目的:找到签名的精确位置,裁剪出签名区域。

python 复制代码
# 步骤1:查找所有外部轮廓
contours, _ = cv2.findContours(
    binary, 
    cv2.RETR_EXTERNAL,        # 只检测外部轮廓
    cv2.CHAIN_APPROX_SIMPLE   # 压缩轮廓,节省内存
)

# 步骤2:过滤小噪声(面积 < 100 像素)
min_area = 100
valid_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_area]

# 步骤3:计算所有有效轮廓的整体边界框
x_min, y_min = float('inf'), float('inf')
x_max, y_max = 0, 0

for contour in valid_contours:
    x, y, w, h = cv2.boundingRect(contour)
    x_min = min(x_min, x)
    y_min = min(y_min, y)
    x_max = max(x_max, x + w)
    y_max = max(y_max, y + h)

# 步骤4:添加边距,让签名不贴边
margin = 20
x_min = max(0, x_min - margin)
y_min = max(0, y_min - margin)
x_max = min(image.shape[1], x_max + margin)
y_max = min(image.shape[0], y_max + margin)

技术亮点

  • 过滤面积过小的轮廓,避免把噪点当成签名
  • 计算所有有效轮廓的联合边界框,确保完整包含签名
  • 添加 20 像素边距,美化效果

5. 透明背景生成(Alpha Channel)

目的:生成带透明背景的 PNG 图片,方便后续使用。

python 复制代码
# 裁剪签名区域
signature_region = binary[y_min:y_max, x_min:x_max]      # 二值图
original_region = image[y_min:y_max, x_min:x_max]        # 原图

# 分离原图的 BGR 三通道
b, g, r = cv2.split(original_region)

# 使用二值图作为 Alpha 通道(透明度)
alpha = signature_region.copy()

# 合并为 BGRA 四通道图像
signature_rgba = cv2.merge([b, g, r, alpha])

原理

  • Alpha 通道 :第四个通道,取值 0-255
    • 0 = 完全透明(背景)
    • 255 = 完全不透明(签名)
  • 使用二值图的白色区域(签名)作为不透明区域
  • 最终保存为 PNG 格式,支持透明度

核心技术特点

1. 智能阈值处理

  • 自适应阈值:根据局部光照自动调整,适应复杂场景
  • 手动调节 :支持用户实时调整阈值(+/- 键),满足不同需求

2. 鲁棒的噪声处理

  • 高斯模糊预处理:降低图像噪声
  • 形态学操作:去除小噪点,平滑签名边缘
  • 面积过滤:过滤掉过小的轮廓

3. 精确的区域定位

  • 外部轮廓检测:只关注主要形状,忽略内部细节
  • 联合边界框:准确框选整个签名,不遗漏笔画
  • 智能边距:自动添加留白,美化效果

4. 高质量输出

  • 透明背景:RGBA 格式,背景完全透明
  • 保留原色:保持签名的原始颜色
  • PNG 格式:无损压缩,支持透明度

完整处理流程

markdown 复制代码
原始图像(BGR彩色图)
    ↓
【1. 预处理】
    → 转灰度图
    → 高斯模糊降噪
    ↓
【2. 二值化】
    → 自适应阈值 / 固定阈值
    → 签名为白色,背景为黑色
    ↓
【3. 形态学处理】
    → 闭运算:填补签名内部小孔
    → 开运算:去除背景噪点
    ↓
【4. 轮廓检测】
    → 查找所有外部轮廓
    → 过滤小面积噪声
    → 计算整体边界框
    ↓
【5. 区域裁剪】
    → 添加边距
    → 裁剪签名区域
    ↓
【6. 透明背景生成】
    → 创建 Alpha 通道
    → 合并 BGRA 图像
    ↓
输出:透明背景 PNG 图片

扩展功能

实时摄像头模式

python 复制代码
def realtime_capture(self, camera_index=0):
    cap = cv2.VideoCapture(camera_index)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)   # 设置分辨率
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
    
    while True:
        ret, frame = cap.read()
        # 实时预览
        cv2.imshow('Camera', frame)
        
        key = cv2.waitKey(1)
        if key == ord('c'):  # 拍照
            signature = self.extract_signature(frame, threshold_value)
        elif key == ord('s'):  # 保存
            self.save_signature(signature)

技术特点

  • 1280×720 高清分辨率
  • 实时预览和反馈
  • 支持阈值动态调节

参数调优建议

参数 默认值 说明 调优建议
高斯模糊核大小 (5, 5) 降噪强度 噪声大用 (7, 7),噪声小用 (3, 3)
自适应阈值邻域 21 局部区域大小 必须为奇数,签名粗用 31,签名细用 11
常数 C 10 阈值调整 背景深用较大值(15-20)
最小面积 100 噪声过滤 高分辨率图像可增大到 500-1000
边距 20 签名留白 根据美观需求调整(10-50)

局限性

  • 极低对比度的签名(如浅灰色签名)
  • 复杂背景(如花纹纸)可能需要手动调节
  • 重叠文字场景需要额外处理

项目GitHub地址

欢迎+Star🌟🌟

相关推荐
Amber_372 小时前
php的数组和python的列表 -- 横向对比学习
python·学习·php
中文Python2 小时前
小白中文Python-双色球LSTM模型出号程序
开发语言·人工智能·python·lstm·中文python·小白学python
superbadguy2 小时前
用curl实现Ollama API流式调用
人工智能·python
嚴 帅2 小时前
Pytnon入门学习(一)
python
小兵张健3 小时前
Java + Spring 到 Python + FastAPI (二)
java·python·spring
vvoennvv3 小时前
【Python TensorFlow】BiTCN-BiLSTM双向时间序列卷积双向长短期记忆神经网络时序预测算法(附代码)
python·rnn·tensorflow·lstm·tcn
程序员爱钓鱼4 小时前
Python 实战:如何读取多格式 Excel 并实现跨表匹配合并(支持 XLS / XLSX)
后端·python·面试
程序员爱钓鱼4 小时前
Python编程实战:实现一个 Excel 批量处理工具(桌面实用脚本)
后端·python·ipython
Solyn_HAN4 小时前
Python 生信进阶:Biopython 库完全指南(序列处理 + 数据库交互)
python·生物信息学·biopython