这里主要记录下我在工作中对倾斜字体文本行的校正的方法探索,废话不多,一起说来看看吧。
目录
一、算法流程图
二、算法实现
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 cstart and end-start <= thres:
k=start
while k
处理后的结果如下:
这个很好计算,这里不多介绍。直接看结果:
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 rcenter_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
最终我们校正后的结果:
参考文献:
一种斜体印刷字倾斜角度检测算法