【中文OCR】中文字符图片的分割方法

最近想做一个关于中文OCR的小系列,也是对之前做的东西的一个总结。作为这个系列的第一篇,我觉得还是有必要说一下关于中文字符图片分割的问题。因为现在开源的OCR代码比较多,相对而言对字符图片的分割的方法提的比较少,尤其是中文字符图片的分割还是有一定困难在里面的。

一、普遍使用的切割方法

现在大部分开源项目上用切割方法还是基于水平、垂直投影字符切割方法。

原理比较简单容易理解,也比较容易实现。先对一个文本图片进行水平投影,得到图片在垂直方向上的像素分布,有像素存在的区域即为文本所在区域;将该行文本切割下来,再对该行文本图片进行垂直投影,得到水平方向的像素分布,同理有像素存在的区域基本字符所在区域。

from PIL import Image
import numpy as np

min_thresh = 2 #字符上最少的像素点
min_range = 5 #字符最小的宽度

def vertical(img_arr):
    h,w = img_arr.shape
    ver_list = []
    for x in range(w):
        ver_list.append(h - np.count_nonzero(img_arr[:, x]))
    return ver_list

def horizon(img_arr):
    h,w = img_arr.shape
    hor_list = []
    for x in range(h):
        hor_list.append(w - np.count_nonzero(img_arr[x, :]))
    return hor_list

def OTSU_enhance(img_gray, th_begin=0, th_end=256, th_step=1):  
    max_g = 0  
    suitable_th = 0  
    for threshold in xrange(th_begin, th_end, th_step):  
        bin_img = img_gray > threshold  
        bin_img_inv = img_gray <= threshold  
        fore_pix = np.sum(bin_img)  
        back_pix = np.sum(bin_img_inv)  
        if 0 == fore_pix:  
            break  
        if 0 == back_pix:  
            continue  

        w0 = float(fore_pix) / img_gray.size  
        u0 = float(np.sum(img_gray * bin_img)) / fore_pix  
        w1 = float(back_pix) / img_gray.size  
        u1 = float(np.sum(img_gray * bin_img_inv)) / back_pix  
        # intra-class variance  
        g = w0 * w1 * (u0 - u1) * (u0 - u1)  
        if g > max_g:  
            max_g = g  
            suitable_th = threshold  
    return suitable_th 

def cut_line(horz, pic):
    begin, end = 0, 0
    w, h = pic.size
    cuts=[]
    for i,count in enumerate(horz):
       if count >= min_thresh and begin == 0:
            begin = i
       elif count >= min_thresh and begin != 0:
            continue
       elif count <= min_thresh and begin != 0:
            end = i
            #print (begin, end), count
            if end - begin >= 2:
                cuts.append((end - begin, begin, end))
                begin = 0
                end = 0
                continue
       elif count <= min_thresh or begin == 0:
            continue
    cuts = sorted(cuts, reverse=True)
    if len(cuts) == 0:
        return 0, False
    else:
        if len(cuts) > 1 and cuts[1][0] in range(int(cuts[0][0] * 0.8), cuts[0][0]):
            return 0, False
        else:
            crop_ax = (0, cuts[0][1], w, cuts[0][2])
    img_arr = np.array(pic.crop(crop_ax))
    return img_arr, True

def simple_cut(vert):
    begin, end = 0,0
 
  • 18
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 48
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 48
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值