Python+opencv 实现图片文字的分割的方法示例

yipeiwu_com6年前Python基础

实现步骤:

1、通过水平投影对图形进行水平分割,获取每一行的图像;

2、通过垂直投影对分割的每一行图像进行垂直分割,最终确定每一个字符的坐标位置,分割出每一个字符;

先简单介绍一下投影法:分别在水平和垂直方向对预处理(二值化)的图像某一种像素进行统计,对于二值化图像非黑即白,我们通过对其中的白点或者黑点进行统计,根据统计结果就可以判断出每一行的上下边界以及每一列的左右边界,从而实现分割的目的。

下面通过Python+opencv来实现该功能

首先来实现水平投影:

import cv2

import numpy as np

 

'''水平投影'''

def getHProjection(image):

 hProjection = np.zeros(image.shape,np.uint8)

 #图像高与宽

 (h,w)=image.shape 

 #长度与图像高度一致的数组

 h_ = [0]*h

 #循环统计每一行白色像素的个数

 for y in range(h):

  for x in range(w):

   if image[y,x] == 255:

    h_[y]+=1

 #绘制水平投影图像

 for y in range(h):

  for x in range(h_[y]):

   hProjection[y,x] = 255

 cv2.imshow('hProjection2',hProjection)

 

 return h_

 

if __name__ == "__main__":

 #读入原始图像

 origineImage = cv2.imread('test.jpg')

 # 图像灰度化 

 #image = cv2.imread('test.jpg',0)

 image = cv2.cvtColor(origineImage,cv2.COLOR_BGR2GRAY)

 cv2.imshow('gray',image)

 # 将图片二值化

 retval, img = cv2.threshold(image,127,255,cv2.THRESH_BINARY_INV)

 cv2.imshow('binary',img)

 #水平投影

 H = getHProjection(img)

通过上面的水平投影,根据其白色小山峰的起始位置就可以界定出每一行的起始位置,从而把每一行分割出来。

获得每一行图像之后,可以对其进行垂直投影

def getVProjection(image):

 vProjection = np.zeros(image.shape,np.uint8);

 #图像高与宽

 (h,w) = image.shape

 #长度与图像宽度一致的数组

 w_ = [0]*w

 #循环统计每一列白色像素的个数

 for x in range(w):

  for y in range(h):

   if image[y,x] == 255:

    w_[x]+=1

 #绘制垂直平投影图像

 for x in range(w):

  for y in range(h-w_[x],h):

   vProjection[y,x] = 255

 cv2.imshow('vProjection',vProjection)

 return w_

通过垂直投影可以获得每一个字符左右的起始位置,这样也就可以获得到每一个字符的具体坐标位置,即一个矩形框的位置。

下面是实现的全部代码:

import cv2

import numpy as np

 

'''水平投影'''

def getHProjection(image):

 hProjection = np.zeros(image.shape,np.uint8)

 #图像高与宽

 (h,w)=image.shape 

 #长度与图像高度一致的数组

 h_ = [0]*h

 #循环统计每一行白色像素的个数

 for y in range(h):

  for x in range(w):

   if image[y,x] == 255:

    h_[y]+=1

 #绘制水平投影图像

 for y in range(h):

  for x in range(h_[y]):

   hProjection[y,x] = 255

 cv2.imshow('hProjection2',hProjection)

 

 return h_

 

def getVProjection(image):

 vProjection = np.zeros(image.shape,np.uint8);

 #图像高与宽

 (h,w) = image.shape

 #长度与图像宽度一致的数组

 w_ = [0]*w

 #循环统计每一列白色像素的个数

 for x in range(w):

  for y in range(h):

   if image[y,x] == 255:

    w_[x]+=1

 #绘制垂直平投影图像

 for x in range(w):

  for y in range(h-w_[x],h):

   vProjection[y,x] = 255

 #cv2.imshow('vProjection',vProjection)

 return w_

 

if __name__ == "__main__":

 #读入原始图像

 origineImage = cv2.imread('test.jpg')

 # 图像灰度化 

 #image = cv2.imread('test.jpg',0)

 image = cv2.cvtColor(origineImage,cv2.COLOR_BGR2GRAY)

 cv2.imshow('gray',image)

 # 将图片二值化

 retval, img = cv2.threshold(image,127,255,cv2.THRESH_BINARY_INV)

 cv2.imshow('binary',img)

 #图像高与宽

 (h,w)=img.shape 

 Position = []

 #水平投影

 H = getHProjection(img)

 

 start = 0

 H_Start = []

 H_End = []

 #根据水平投影获取垂直分割位置

 for i in range(len(H)):

  if H[i] > 0 and start ==0:

   H_Start.append(i)

   start = 1

  if H[i] <= 0 and start == 1:

   H_End.append(i)

   start = 0

 #分割行,分割之后再进行列分割并保存分割位置

 for i in range(len(H_Start)):

  #获取行图像

  cropImg = img[H_Start[i]:H_End[i], 0:w]

  #cv2.imshow('cropImg',cropImg)

  #对行图像进行垂直投影

  W = getVProjection(cropImg)

  Wstart = 0

  Wend = 0

  W_Start = 0

  W_End = 0

  for j in range(len(W)):

   if W[j] > 0 and Wstart ==0:

    W_Start =j

    Wstart = 1

    Wend=0

   if W[j] <= 0 and Wstart == 1:

    W_End =j

    Wstart = 0

    Wend=1

   if Wend == 1:

    Position.append([W_Start,H_Start[i],W_End,H_End[i]])

    Wend =0

 #根据确定的位置分割字符

 for m in range(len(Position)):

  cv2.rectangle(origineImage, (Position[m][0],Position[m][1]), (Position[m][2],Position[m][3]), (0 ,229 ,238), 1)

 cv2.imshow('image',origineImage)

 cv2.waitKey(0)

从分割的结果上看,基本上实现了图片中文字的分割。但由于中文结构复杂性,对于一些文字的分割并不理想,比如“叶”、“桃”等字会出现过度分割现象;对于有粘连的两个字会出现分割不够的现象,比如上图中的“念想”。不过可以从图像预处理(腐蚀),边界判断阈值的调整等方面进行优化。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

python获取网页中所有图片并筛选指定分辨率的方法

python获取网页中所有图片并筛选指定分辨率的方法

压测时,图片太少,想着下载网页中的图片,然后过滤指定分辨率,但网页中指定分辨率的图片太少了(见下) 后使用格式工厂转换图片 import urllib.request # 导入...

Python中的fileinput模块的简单实用示例

这几天有这样一个需求,要将用户登陆系统的信息统计出来,做成一个报表。当用户登陆成功的时候,服务器会往日志文件里写一条像下面这种格式的记录:”日期时间@用户名@IP“,这样的日志文件第天生...

django之自定义软删除Model的方法

软删除 简单的说,就是当执行删除操作的时候,不正真执行删除操作,而是在逻辑上删除一条记录。这样做的好处是可以统计数据,可以进行恢复操作等等。 预备知识 Managers Mana...

Python Flask 搭建微信小程序后台详解

前言: 近期需要开发一个打分的微信小程序,涉及到与后台服务器的数据交互,因为业务逻辑相对简单,故选择Python的轻量化web框架Flask来搭建后台程序。因为是初次接触小程序,经过一番...

Python面向对象程序设计多继承和多态用法示例

Python面向对象程序设计多继承和多态用法示例

本文实例讲述了Python面向对象程序设计多继承和多态用法。分享给大家供大家参考,具体如下: 多继承 就是一个子类继承多个父类: 多继承的例子,如下: # -*- coding:u...