这个工具可以将比较工整的白底黑字手写签名照片转换成背景透明的签名照片,从而可以在电子版的文件上通过覆盖一层图片来实现手写签名的效果。
代码如下:
from PIL import Image
import os
import time
import numpy as np
def sign(fp, threshold=120,region=None):
'''
# fp: 需要转换的图片路径
# threshold: 图像二值化阈值,灰度大于阈值则变成255(白色),否则则变成0(黑色)
# region: 裁剪图像的范围(x0, y0, x1, y1)
'''
# 读取图片
img = Image.open(fp)
# 保存为灰度图片
img = img.convert('L')
# 转换为数组
aimg = np.asarray(img)
# 二值化
aimgb = np.where(aimg>threshold, 255, 0)
# 生成alpha通道
aalpha = np.where(aimg>threshold, 0, 255)
# 将数组转换为Image对象
imgb = Image.fromarray(np.uint8(aimgb))
alpha = Image.fromarray(np.uint8(aalpha))
# 为二值化的Image对象添加alpha通道
imgb.putalpha(alpha) # 也可以对原图添加alpha通道,这样就可以保留原始笔迹颜色
# 剪切图像(x0, y0, x1, y1)
if region:
imgb = imgb.crop(region)
# 储存图片
path, _ = os.path.split(fp)
fname_ = 'sign_{:.0f}.png'.format(time.time()*100)
imgb.save(os.path.join(path, fname_))
这个函数的工作原理就是将签名图片二值化,然后插入alpha通道,使白色的地方变成全透明。图像二值化的阈值参数threshold小,签名照片的背景干扰程度越小,但是签名部分也可能会损失一部分细节。
下面来举个例子,我在网上找到了一个号称是梁朝伟的签名:

可以看出四个叫比较黑,下面还有浅色的签字。
当threshold分别取30和80时,会生成如下图片:


可以看出,当threshold=30时,签名部分的细节有损失,看着像签字笔没墨水一样;而threshold=80时,签字没毛病,但是就会出现背景干扰(这里是暗角)。
我们可以进一步调低threshold参数,或者可以简单粗暴地用画图板把原照片上黑角的位置抹白。我觉得一般用用的话,后者比较方便,当然也可以添加代码来识别黑角(比如可以计算像素的梯度,黑角部分的像素点虽然深,但是整体梯度小)。


像这样就会好很多。。

本文介绍了一种将手写签名照片转换为背景透明的签名图片的方法,利用Python的PIL库进行图像二值化和透明通道处理,实现了在电子文档上的手写签名效果。
215

被折叠的 条评论
为什么被折叠?



