Python手写签名相似度匹配:如何提升示例2的结果准确性?
提升手写签名相似度匹配精度的优化方案
针对视觉相似签名(示例2)SSIM匹配得分偏低的问题,核心原因是当前方案仅依赖全局结构相似性,未处理签名的几何形变(平移、缩放、旋转)、笔画粗细差异等问题。以下是具体优化方向及代码实现:
1. 加入几何对齐:用特征匹配实现仿射变换对齐
示例2中两个签名存在明显的缩放和位置偏移,直接resize会导致笔画错位。通过特征点匹配计算变换矩阵,将两张签名对齐到同一坐标系:
import cv2 import numpy as np def align_signatures(img1, img2): # 初始化ORB特征检测器 orb = cv2.ORB_create(500) kp1, des1 = orb.detectAndCompute(img1, None) kp2, des2 = orb.detectAndCompute(img2, None) # 暴力匹配特征点 matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = matcher.match(des1, des2) matches = sorted(matches, key=lambda x: x.distance) # 提取匹配的关键点对 src_pts = np.float32([kp1[m.queryIdx].pt for m in matches[:100]]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches[:100]]).reshape(-1, 1, 2) # 计算单应性矩阵并做透视变换 M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) h, w = img1.shape aligned_img1 = cv2.warpPerspective(img1, M, (w, h)) return aligned_img1, img2
在match函数中,替换resize步骤为对齐操作:
# 原resize代码替换为: img1, img2 = align_signatures(img1, img2) # 再统一resize到相同尺寸 img1 = cv2.resize(img1, (300, 300)) img2 = cv2.resize(img2, (300, 300))
2. 优化预处理:加入形态学操作与笔画归一化
签名的笔画粗细、噪声会影响SSIM计算,加入二值化、形态学处理和骨架提取,统一笔画特征:
def preprocess_signature(img): # 去白边 img = removeWhiteSpace(img) # 灰度化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化(应对光照不均) binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 形态学开运算消除噪声,闭运算填补笔画缺口 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2)) binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) # 骨架提取(归一化笔画宽度) skeleton = cv2.ximgproc.thinning(binary) return skeleton
修改match函数中的预处理步骤,用preprocess_signature替代原有的灰度化和resize前的操作。
3. 替换SSIM为更适合签名的匹配算法
SSIM对全局结构变化敏感,可改用基于轮廓特征的匹配方法,比如Hu不变矩:
def calculate_similarity_hu(img1, img2): # 提取轮廓 contours1, _ = cv2.findContours(img1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours2, _ = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 计算Hu矩 if contours1 and contours2: cnt1 = max(contours1, key=cv2.contourArea) cnt2 = max(contours2, key=cv2.contourArea) hu1 = cv2.HuMoments(cv2.moments(cnt1)).flatten() hu2 = cv2.HuMoments(cv2.moments(cnt2)).flatten() # 计算Hu矩的相似度(取对数后计算欧氏距离) hu1 = -np.sign(hu1) * np.log10(np.abs(hu1)) hu2 = -np.sign(hu2) * np.log10(np.abs(hu2)) distance = np.linalg.norm(hu1 - hu2) # 转换为相似度百分比(距离越小相似度越高) similarity = 100 - (distance / np.max([hu1.max(), hu2.max()]) * 100) return round(similarity, 2) return 0.0
4. 混合匹配策略:结合SSIM与局部特征
如果不想完全替换SSIM,可以结合局部特征匹配的结果,加权计算最终相似度:
def hybrid_similarity(img1, img2): ssim_score = ssim(img1, img2, gaussian_weights=True, sigma=1.2, use_sample_covariance=False)*100 hu_score = calculate_similarity_hu(img1, img2) # 加权平均,可根据实际效果调整权重 return round((ssim_score * 0.4 + hu_score * 0.6), 2)
通过以上优化,示例2中的签名匹配得分会显著提升,同时也能增强整体匹配算法的鲁棒性。
内容的提问来源于stack exchange,提问作者Ahmed Ansari
相关产品推荐
相关产品推荐

