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

项目简介

这是一个基于 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🌟🌟

相关推荐
老白干8 小时前
jjwt 0.9.1 在 JDK 11+ 上的两个“坑”与完整解决方案
java·python·log4j
笨鸟先飞,勤能补拙14 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能15 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂16 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study16 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境17 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境17 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12317 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy123931021618 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb0018 小时前
一个项目带你入门AI应用开发01
python