You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV形态学开运算后填充签名图像缺口的方法

解决签名图像网格线去除后缺口问题的方案

核心思路

先精准定位所有网格线(水平+垂直)生成掩码,再通过图像修复或受限形态学操作填补缺口,避免直接闭运算导致的过度填充。


方案一:基于图像修复的精准修复(推荐)

利用cv2.inpaint根据周围像素智能填补网格线位置的缺口,不会破坏签名原有结构:

import cv2
import numpy as np

# 1. 加载图像并预处理
image = cv2.imread('Downloads/image.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化(适配签名深色、网格线浅色的场景,INV后签名为白色)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# 2. 检测水平网格线
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40, 1))  # 数值根据网格线间距调整
horizontal_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)

# 3. 检测垂直网格线
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 40))  # 数值根据网格线间距调整
vertical_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)

# 4. 合并网格线掩码并优化
grid_mask = cv2.add(horizontal_lines, vertical_lines)
grid_mask = cv2.dilate(grid_mask, None, iterations=1)  # 轻微膨胀确保覆盖完整网格线

# 5. 图像修复+二次二值化
restored_gray = cv2.inpaint(gray, grid_mask, 3, cv2.INPAINT_TELEA)
final_thresh = cv2.threshold(restored_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# 保存结果
cv2.imwrite('Downloads/out.png', final_thresh)

关键细节

  • 结构元素调整:(40,1)和(1,40)的数值需匹配你的网格线间距,确保只检测网格线而非签名笔画。
  • 修复算法选择:cv2.INPAINT_TELEA适合细小线条修复,效果不佳时可替换为cv2.INPAINT_NS(基于Navier-Stokes方程)。
  • 二次二值化:修复后的灰度图再次二值化,能消除修复带来的灰度过渡,保证签名边缘清晰。

方案二:受限形态学填充(针对缺口精准处理)

通过签名掩码限制闭运算的作用范围,仅填充签名内部缺口,避免影响背景区域:

import cv2
import numpy as np

# 原代码处理网格线部分
image = cv2.imread('Downloads/image.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# 去除水平线
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50,1))
detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (0,0,0), 2)

# 新增:精准填充缺口
# 提取签名轮廓
cnts_signature = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts_signature = cnts_signature[0] if len(cnts_signature) == 2 else cnts_signature[1]
# 创建签名掩码(仅保留签名区域)
signature_mask = np.zeros_like(thresh)
cv2.drawContours(signature_mask, cnts_signature, -1, 255, thickness=cv2.FILLED)
# 仅在签名掩码内执行闭运算填充缺口
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
filled_thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)
# 保留签名区域的填充结果
final_thresh = cv2.bitwise_and(filled_thresh, signature_mask)

cv2.imwrite('Downloads/out.png', final_thresh)

内容的提问来源于stack exchange,提问作者anonR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:20:33