字符分割有很多方法,但并不是每一种方法是万能的,那么就需要根据自己的需要来分析。
例如:我现在项目的需求是将一串编号给切分开来。查了网上的资料和文献,大致适合项目的有两种方法:投影分割法和连通域分割法。
当然还有其他的一些改进的算法,今天就不作深入讨论,以后研究了再分享。今天我们就来实现垂直投影和水平投影
首先是我们的原图片
垂直投影方法
(h,w)=thresh2.shape a = [0 for z in range(0, w)] for j in range(0,w): for i in range(0,h): if thresh2[i,j]==0: a[j]+=1 thresh2[i,j]=255 for j in range(0,w): for i in range((h-a[j]),h): thresh2[i,j]=0
水平投影方法
(h,w)=thresh1.shape a = [0 for z in range(0, h)] for j in range(0,h): for i in range(0,w): if thresh1[j,i]==0: a[j]+=1 thresh1[j,i]=255 for j in range(0,h): for i in range(0,a[j]): thresh1[j,i]=0
垂直投影的结果:
水平投影的结果:
接下来是完整代码:
import cv2 import numpy as np from PIL import Image #灰度图片进行二值化处理 img=cv2.imread('123.jpg') GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh1=cv2.threshold(GrayImage,130,255,cv2.THRESH_BINARY) ret,thresh2=cv2.threshold(GrayImage,130,255,cv2.THRESH_BINARY) #水平投影 (h,w)=thresh1.shape a = [0 for z in range(0, h)] for j in range(0,h): for i in range(0,w): if thresh1[j,i]==0: a[j]+=1 thresh1[j,i]=255 for j in range(0,h): for i in range(0,a[j]): thresh1[j,i]=0 #垂直投影 (h,w)=thresh2.shape a = [0 for z in range(0, w)] for j in range(0,w): for i in range(0,h): if thresh2[i,j]==0: a[j]+=1 thresh2[i,j]=255 for j in range(0,w): for i in range((h-a[j]),h): thresh2[i,j]=0 #展示图片 cv2.imshow("src",img) cv2.imshow('img',thresh1) cv2.imshow('img2',thresh2) cv2.waitKey(0) cv2.destroyAllWindows()
投影法的原理其实很简单,利用二值化图片的像素的分布直方图进行分析,从而找出相邻字符的分界点进行分割。
总结:做图像分割的时候要选择合适的方法,例如我这张样本图的布局是左右型,就适合用垂直投影的方法,反之若是上下型,则做水平投影即可。
若图像内的字符是纵横交错的话就需要先垂直投影分割再水平分割,或者采用连通域分割法,取出字符范围。