python用直方图峰值法分割挨得近的字母或数字

背景

做文字识别时,发现字符挨得太近,容易误识别。
最开始用形态学开运算,分不开字符间的搭接。
之后选择了下面的办法,图像二值化,按列统计白点个数(这时候的波谷就是字符间的界线,可是没有找波谷的函数,所以变成了下面的过程),反转(用列表中的最大值,减去每个值,得到新列表),寻找波峰,按波峰位置分割字符,将分割开的字符进行形态学腐蚀运算,去除毛刺,大功告成。

代码

#coding:utf-8
from scipy import signal
from scipy.ndimage.morphology import binary_fill_holes
import matplotlib.pyplot as plt
import numpy as np
import cv2

#读取图片
img = cv2.imread(r'包含一行字符的图片文件', 0)
#图像二值化
thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 图像取反,字符变为黑色
img = ~thresh
# 填充字符中的空洞,便于直方图统计白点,寻找字符间的界线。
thresh = np.array(binary_fill_holes(thresh,np.ones((3,3))),dtype=np.uint8)*255
print('thresh',thresh.max(),thresh.min())
cv2.imshow('thresh', thresh)

# 统计每列的白点个数
rows,cols = thresh.shape[:2]
list0 = np.zeros((cols))
for i in range(cols):
    list0[i] = np.count_nonzero((thresh[:, i]).ravel())
# 将白点分布情况绘制直方图
vProjection = np.zeros(thresh.shape[:2],np.uint8)
print(vProjection.shape)
for i in range(cols):
    if list0[i]>0:
        vProjection[int(rows-list0[i]):,i]=255
cv2.imshow('vProjection',vProjection)
cv2.waitKey(0)

#绘制波峰。
# 由于有找波峰的函数,没有找波谷的函数。所以这里将获得的白点个数列表用最大值做了一个减法,把波谷转换为波峰。
list1 = list0.max()-list0
# 间距distance根据自己的图片来调。这里会漏掉一些极大值点
peaks1,_ = signal.find_peaks(list1,distance=18)
# 用这个把上面漏掉的极大值(即原先为0)的点补充上
peaks2,_ = signal.find_peaks(list1,height=list1.max()-1)#样本要高于这个高度才被查找
print(peaks1)
print(peaks2)
# 将数组转换为列表
peaks1 = list(peaks1)
peaks2 = list(peaks2)
# 将两个列表合并,去除重复值,由小到大排序
peaks = sorted(list(set(peaks1+peaks2)))
print(peaks,'peaks')
plt.plot(list1)
plt.plot(peaks,list1[peaks],'x')
plt.show()
cv2.imshow('beforeimg',img)
cv2.waitKey(0)
# 根据获得的波峰分割字符
jianju = 3
move_steps = [0]
for j in peaks:
    img = np.insert(img, j + sum(move_steps), [[255]] * (jianju), axis=1)  # 保证文字的间距为jianju
    move_steps.append(jianju)
# 为了去除分割过程中产生的毛刺,进行腐蚀操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3),anchor=(-1,-1))
img = ~cv2.morphologyEx(~img,cv2.MORPH_ERODE,kernel,anchor=(-1,-1),iterations=1)
# 展示图片
cv2.imshow('imgfinal',img)
cv2.waitKey(0)

处理结果,由下向上看

python用直方图峰值法分割挨得近的字母或数字_第1张图片
python用直方图峰值法分割挨得近的字母或数字_第2张图片

你可能感兴趣的:(opencv,python,开发语言,计算机视觉)