这里主要记录下我在工作中对倾斜字体文本行的校正的方法探索,废话不多,一起说来看看吧。
目录
一、算法流程图
二、算法实现
2.1、预处理
2.2、水平模糊
2.3、垂直投影
2.4、短斜线倾斜角度的统计计算
2.5、倾斜校正
三、算法实现的最终结果
实现倾斜文本行字体的校正主要分为两部分,一部分为倾斜角度的检测,另一部分为倾斜校正。其中倾斜角度的检测极为重要,他关系到后续的校正。
原始图片:
这里主要是灰度化、滤波以及二值化,结果如下:
水平模糊也叫做游程平滑。是将图像上长度小于某一域值的连续黑点转为白点的演算法则。图像经模糊算法处理后, 图像上距离相近的连通成份将会形成为一较大的连通区域。
def horizontal_blur(image): '''水平平滑''' dst=image #计算图像的字符宽度 hor_vec=np.sum(dst,axis=0) width=hor_vec.shape[0] left=right=0 for i in range(width): if hor_vec[i]!=0: left=i break for j in range(width-1,-1,-1): if hor_vec[j]!=0: right=j break char_width=right-left+1 if right-left+1>0 else 10 # 计算游程平滑阈值 thres=char_width//10 h,w=dst.shape for r in range(h): c=0 while c<w and dst[r,c]==0: c+=1 max_w=0 for i in range(w-1,-1,-1): if dst[r,i] !=0: max_w=i break start=0 end=0 flag=True for j in range(c,max_w): if flag and dst[r,j]==0: start=j flag=False if not flag and dst[r,j]!=0: end=j if end>start and end-start <= thres: k=start while k<end: dst[r,k]=255 k+=1 flag=True return dst
处理后的结果如下:
这个很好计算,这里不多介绍。直接看结果:
1、垂直投影测角原理
那么倾斜角度的计算公式为:
也就是说我们可以通过上图第二个图来计算倾斜字体的角度,而第二张图就是我们的投影曲线了。所以我们计算投影曲线的角度也就是我们的倾斜角度。
需要注意的是:模糊区域边界部分投影曲线形状与字符 结构有较大关系, 例如字符边界不是竖直笔画 ( 英文字母 X)或边界笔画反而会干扰倾斜角度取得的字符 ( A, W等 ), 因此并非所有短斜线的斜率都是斜体字的斜率。 一般地, 正确的折线数量大于不正确的 。基于此, 本文在设计算法时采用 投票法来获取正确角度, 即对于得到的所有角度, 通过投票获知哪个角度出现的次数最多, 该角度就是要找的倾斜角度。
2、代码实现
这里代码不多详述,因为代码是公司的,所以能不能再贴了,有需要的小伙伴可以私底下聊,我会经量帮你解决。
def bilinear_interpolation(image,angle,center,y_min,y_max): '''对倾斜字体进行双线性插值''' center_x, center_y=center h,w=image.shape dst=np.zeros((h,w),dtype=np.uint8) for r in range(h): for c in range(w): #计算原图上的坐标 i = r if r<center_y: j=c+(center_y-r)/math.tan(angle) elif r>center_y: j=c-(r-center_y)/math.tan(angle) else: j=c #计算源图上的四个近邻点 x_0=max(int(np.floor(j)),0) y_0=max(int(np.floor(i)),0) x_1=min(x_0+1,w-1) y_1=min(y_0+1,h-1) #双线性插值 if (x_0 >=x_1) or (y_0>=y_1): continue value0=((x_1-j)*image[y_0,x_0]+(j-x_0)*image[y_0,x_1]) value1=((x_1-j)*image[y_1,x_0]+(j-x_0)*image[y_1,x_1]) dst[r,c]=int(((y_1-i)*value0+(i-y_0)*value1)) return dst def correct_slanted_fonts(image,mask,angle): '''倾斜字体的矫正''' h,w=mask.shape # 计算倾斜字体的中心点 center_x=0 center_y=0 num=0 for r in range(h): for c in range(w): if mask[r,c]==255: center_x+=c center_y+=r num+=1 center_x=center_x//num center_y=center_y//num #计算文本的上下边界 ver_vec=np.sum(mask,axis=1) up=0 down=0 h=ver_vec.shape[0] for i in range(h): if ver_vec[i]!=0: up=i break for i in range(h-1,-1,-1): if ver_vec[i]!=0: down=i break #对图像进行双线性插值 dst=bilinear_interpolation(image,angle,(center_x,center_y),up,down) # cv2.namedWindow("test1",0) # cv2.imshow("test1", dst) # cv2.waitKey(0) return dst
最终我们校正后的结果:
参考文献:
一种斜体印刷字倾斜角度检测算法