什么是tesseractOCR?
这篇就讲解一下软件安装、使用自带的识别库识别常规的英文字符、英文单词、数字。
目录
tesseract下载与安装:
1、软件下载(后面会放我自己下载好的网盘链接,可以自行下载):
2、软件安装:
3、环境变量的设置:
识别时所需要的库:
英文字符的识别:
1、先导入咱们安装好的tesseract软件以及所需要识别的图片。
2、识别。
3、在图片上面框选出字符,并且将字符的识别结果显示在图片上。
完整代码:
英文单词的识别:
完整代码:
数字的识别:
完整代码:
软件:pycharm
这里是tesseract的下载官网,任意版本的都可以,但不要下载带有dev标识的版本。
没有速度快的梯子的话,速度会很慢。但我没有梯子,好像就下了十来分钟左右。
这里就必须强调有无梯子的事了。
双击下载好的exe文件,一路next,直到这个界面注意一下:
按顺序点击:此电脑---属性---高级系统设置---环境变量。
选中path那一行,点击“编辑”。
在弹窗内点击“新建”,将安装tesseract软件的文件夹的绝对路径放进去。我这里是D:\OpencvPython\01使用tessdoc进行文本检测\tesseract。
确定之后,在此界面点击“新建”:
输入变量名和变量值:(变量值是tesseract软件下面的tessdata文件的绝对路径)
变量名:TESSDATA_PREFIX
变量值:D:\OpencvPython\01使用tessdoc进行文本检测\tesseract\tessdata
剩下的就是不停的点击确定。环境变量设置结束。
在cmd里输入:tesseract --version
出现版本号了就是下载成功了。
这是我自己下载好的软件和压缩包的网盘链接,自行下载:
链接:https://pan.baidu.com/s/1-dP6-QauGDjBsvo8v8_Gyw
提取码:cimx
import cv2
import pytesseract
这里注意一下:tesseract只能识别RGB格式的图片,而opencv导进来的图片是BGR格式的。
pytesseract.pytesseract.tesseract_cmd = 'D:\\OpencvPython\\01使用tessdoc进行文本检测\\tesseract\\tesseract.exe'
img = cv2.imread('eng.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
图片:
text = pytesseract.image_to_string(img)
print(text)
结果:(挺成功的)
hImg, wImg, _ = img.shape
boxes = pytesseract.image_to_boxes(img)
for b in boxes.splitlines():
b = b.split(' ')
x1, y1, x2, y2 = int(b[1]), int(b[2]), int(b[3]), int(b[4])
cv2.rectangle(img, (x1,hImg-y1), (x2, hImg-y2), (0, 0, 255), 2)
cv2.putText(img, b[0], (x1, hImg-y1+25), cv2.FONT_HERSHEY_SIMPLEX, 1, (50, 50, 255), 2)
结果:
来拆解一下这组代码的含义:
hImg, wImg, _ = img.shape
boxes = pytesseract.image_to_boxes(img)
img,shape输出的是原始图片img的高度、宽度、纬度
boxes如下图所示,里面包含着每个字符的识别结果和该字符所在的位置信息。
比如:H 32 58 75 99 。含义依次是左下角横坐标,左下角纵坐标,右上角横坐标,右上角纵坐标。这个位置信息需要额外注意一下:pytesseract.image_to_boxes的坐标系原点在左下角,而opencv的坐标系原点在左上角。
要想从这些字符串里面取出来数据,引入一个for循环。
for b in boxes.splitlines(): # 这里将boxes的元素一行一行地取出
for b in boxes.splitlines():
b = b.split(' ') # 这里将b里面的元素,出现空格就分开
b里面的数据:
再次强调:pytesseract.image_to_boxes的坐标系原点在左下角,而opencv的坐标系原点在左上角。
将坐标转换成opencv里面需要的坐标。
先小结一下相关变量的含义:
hImg : 图片的总高度; wImg : 图片的总宽度
x1: 字符的左下角横坐标; y1:字符的左下角纵坐标
x2: 字符的左上角横坐标; y2:字符的左上角纵坐标
大概画一张图:
根据线段长度之类的转换,很成功地得到了坐标。
使用cv2.rectangle函数,画出外框。
使用cv2.putText放置文本内容。
最后的结果为:
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = 'D:\\OpencvPython\\01使用tessdoc进行文本检测\\tesseract\\tesseract.exe'
img = cv2.imread('eng.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
text = pytesseract.image_to_string(img)
print(text)
hImg, wImg, _ = img.shape
boxes = pytesseract.image_to_boxes(img)
for b in boxes.splitlines():
b = b.split(' ')
x1, y1, x2, y2 = int(b[1]), int(b[2]), int(b[3]), int(b[4])
cv2.rectangle(img, (x1,hImg-y1), (x2, hImg-y2), (0, 0, 255), 2)
cv2.putText(img, b[0], (x1, hImg-y1+25), cv2.FONT_HERSHEY_SIMPLEX, 1, (50, 50, 255), 2)
cv2.imshow('Result', img)
cv2.waitKey(0)
如何做到把字符连起来形成单词的样子?
和英文字符的识别差别只在第三步。这里就放上第三步的代码。
hImg, wImg, _ = img.shape
boxes = pytesseract.image_to_data(img)
print(boxes)
for x,b in enumerate(boxes.splitlines()):
if x!=0:
b = b.split()
print(b)
if len(b)==12:
x1, y1, x2, y2 = int(b[6]), int(b[7]), int(b[8]), int(b[9])
cv2.rectangle(img, (x1,y1), (x1+x2, y1+y2), (0, 0, 255), 3)
cv2.putText(img, b[11], (x1,y1), cv2.FONT_HERSHEY_SIMPLEX, 1, (50, 50, 255), 2)
这里调用的函数是 image_to_data,前面调用的函数是image_to_boxes。
boxes = pytesseract.image_to_data(img)
这个函数输出的boxes就多样化了,但咱只需要第7、8、9、10、12列的数据。
for循环的语句里
boxes.splitlines()还是将boxes按行分开
而enumerate(a)函数会将a里的每一个元素单独拆分出来,并且加上索引,以元组的形式返回。
所以,for x,b in enumerate(boxes.splitlines()),x放的是索引号。后面再加上一个x!=0的条件句,就是为了去掉boxes里第一行的“level、page_num、block_num...”。
再看看boxes里面的十二列数据,会发现有的行只有11个数据,-1代表没有识别出东西来。而能够识别出来的都会有12个数据,咱需要的也就是有12个数据的那些行,因此又有了len(b)==12的条件句。
剩下的三行代码和识别字符一样的含义。
最后识别英文单词的结果:
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = 'D:\\OpencvPython\\01使用tessdoc进行文本检测\\tesseract\\tesseract.exe'
img = cv2.imread('eng.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
text = pytesseract.image_to_string(img)
print(text)
hImg, wImg, _ = img.shape
boxes = pytesseract.image_to_data(img)
print(boxes)
for x,b in enumerate(boxes.splitlines()):
if x!=0:
b = b.split()
print(b)
if len(b)==12:
x1, y1, x2, y2 = int(b[6]), int(b[7]), int(b[8]), int(b[9])
cv2.rectangle(img, (x1,y1), (x1+x2, y1+y2), (0, 0, 255), 3)
cv2.putText(img, b[11], (x1,y1), cv2.FONT_HERSHEY_SIMPLEX, 1, (50, 50, 255), 2)
cv2.imshow('Result', img)
cv2.waitKey(0)
其实在英文字符的识别里面,就可以完成对数字的识别了。
识别的结果:
使用英文字符识别的代码,既有英文又有数字的识别结果:
但你要是只想识别出数字:
那就在boxes那里加个限制条件:让oem为3,psm为6。
cong = r'--oem 3 --psm 6 outputbase digits'
boxes = pytesseract.image_to_boxes(img, config=cong)
-oem 参数控制OCR的引擎模式,控制由超正方体使用的算法类型。
oem的数值代表的模式:
-psm 参数控制tesseract使用的自动页面分割模式。
psm的数值代表的模式:
识别结果:
很明显,加上了限制条件,它确实只能够识别准确数字,其他类型的东西效果很不理想,甚至不能识别(理论上是不能识别的)。
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = 'D:\\OpencvPython\\01使用tessdoc进行文本检测\\tesseract\\tesseract.exe'
img = cv2.imread('eng.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
text = pytesseract.image_to_string(img)
print(text)
hImg, wImg, _ = img.shape
cong = r'--oem 3 --psm 6 outputbase digits'
boxes = pytesseract.image_to_boxes(img, config=cong)
for b in boxes.splitlines():
b = b.split(' ')
x1, y1, x2, y2 = int(b[1]), int(b[2]), int(b[3]), int(b[4])
cv2.rectangle(img, (x1,hImg-y1), (x2, hImg-y2), (0, 0, 255), 2)
cv2.putText(img, b[0], (x1, hImg-y1+25), cv2.FONT_HERSHEY_SIMPLEX, 1, (50, 50, 255), 2)
cv2.imshow('Result', img)
cv2.waitKey(0)