(读者电脑中应安装有Canopy)
先下载tesseract-ocr模块:OCR模块
将其安装在Canopy那个盘。
安装了之后,下载代码:代码
将代码解压至......\Canopy\User\Lib\site-packages
然后在Canopy内运行代码文件中的pytesser.py即可。
PS:
# -*- coding: utf-8 -*-
import os
import wx
import util
import errors
import urllib2
import subprocess
from PIL import Image
os.chdir('D:\Canopy\User\Lib\site-packages\pytesser_v0.0.1')
tesseract_exe_name = 'tesseract' # Name of executable to be called at command line
scratch_image_name = "temp.bmp" # This file must be .bmp or other Tesseract-compatible format
scratch_text_name_root = "temp" # Leave out the .txt extension
cleanup_scratch_flag = True # Temporary files cleaned up after OCR operation
def call_tesseract(input_filename, output_filename):
"""Calls external tesseract.exe on input file (restrictions on types),
outputting output_filename+'txt'"""
args = [tesseract_exe_name, input_filename, output_filename]
proc = subprocess.Popen(args)
retcode = proc.wait()
if retcode!=0:
errors.check_for_errors()
def image_to_string(im, cleanup = cleanup_scratch_flag):
"""Converts im to file, applies tesseract, and fetches resulting text.
If cleanup=True, delete scratch files after operation."""
try:
util.image_to_scratch(im, scratch_image_name)
call_tesseract(scratch_image_name, scratch_text_name_root)
text = util.retrieve_text(scratch_text_name_root)
finally:
if cleanup:
util.perform_cleanup(scratch_image_name, scratch_text_name_root)
return text
def image_file_to_string(filename, cleanup = cleanup_scratch_flag, graceful_errors=True):
"""Applies tesseract to filename; or, if image is incompatible and graceful_errors=True,
converts to compatible format and then applies tesseract. Fetches resulting text.
If cleanup=True, delete scratch files after operation."""
try:
try:
call_tesseract(filename, scratch_text_name_root)
text = util.retrieve_text(scratch_text_name_root)
except errors.Tesser_General_Exception:
if graceful_errors:
im = Image.open(filename)
text = image_to_string(im, cleanup)
else:
raise
finally:
if cleanup:
util.perform_cleanup(scratch_image_name, scratch_text_name_root)
return text
class MyModalDialog(wx.Dialog):
def __init__(self, parent, title):
super(MyModalDialog, self).__init__(parent, title = title, pos = (500, 300), size = (950, 580)) # 调用父类构造器(必须)
panel = wx.Panel(self)
wx.StaticText(panel, -1, u"Folder: ", pos=(5, 5), size=(60, 30))
self.imagePath = wx.TextCtrl(panel, pos=(65, 5), size=(400, 30))
self.imagePath.SetLabel(os.getcwd())
wx.StaticText(panel, -1, u"Files of type: ", pos=(5, 40), size=(100, 30))
sampleList = ['tif files(*.tif)|*.tif', 'png files(*.png)|*.png', 'jpg files(*.jpg)|*.jpg']
self.combobox = wx.ComboBox(panel, -1, "tif files(*.tif)|*.tif", (105, 40), wx.DefaultSize, sampleList, wx.CB_DROPDOWN)
self.Bind(wx.EVT_TEXT, self.comboboxChange, self.combobox)
wx.Button(panel, 300, label = u"up one level", pos = (500, 5), size = (100, 30))
wx.Button(panel, 301, label = u"Browse for a folder", pos=(650, 5), size=(150, 30))
wx.Button(panel, 302, label = u"Open", pos = (30, 500), size = (100, 30))
wx.Button(panel, 303, label = u"Cancel", pos = (170, 500), size = (100, 30))
self.Bind(wx.EVT_BUTTON, self.Back, id = 300)
self.Bind(wx.EVT_BUTTON, self.FileDialog, id = 301)
self.Bind(wx.EVT_BUTTON, self.Ok, id = 302)
self.Bind(wx.EVT_BUTTON, self.Cancel, id = 303)
self.bitmap = wx.StaticBitmap(panel, -1, pos = (350, 45))
self.list = wx.ListBox(panel, -1, (5, 100), (300, 300), '', wx.LB_SINGLE) # 文件夹listbox
self.list.Bind(wx.EVT_LISTBOX_DCLICK, self.OnDClick)
curdir = os.getcwd() # 设置初始路径
self.LoadDir(curdir) # 加载初始文件夹
self.Bind(wx.EVT_CLOSE, self.OnClose) # 绑定事件
def OnClose(self, event):
self.Destroy()
def comboboxChange(self, event):
self.LoadDir(os.getcwd())
def OnDClick(self, event): # listbox双击事件
if self.list.GetSelection() == 0: # 判断是否选择了返回上一层文件夹
path = os.getcwd()
pathinfo = os.path.split(path)
dir = pathinfo[0]
else: # 获得需要进入的下一层文件夹
dir = self.list.GetStringSelection()
if os.path.isdir(dir): # 进入文件夹
self.LoadDir(dir)
else:
path = os.getcwd()
self.imagePath.SetLabel(path + os.path.sep + dir)
# 这里之所以把SetSize放在SetBitmap的后面,是因为这样可以让图片显示在中心
tempBitmap = wx.Image(dir, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap.SetBitmap(tempBitmap)
self.bitmap.SetSize((580, 450))
def LoadDir(self, dir): # 加载文件夹
self.list.Clear() # 清空
self.list.Append('...') # 添加返回上一层文件夹标志
# 从combobox中获取选中的后缀,保存在suffix中
value = self.combobox.GetValue()
length = len(value)
temp = []
temp.append(value[length - 4])
temp.append(value[length - 3])
temp.append(value[length - 2])
temp.append(value[length - 1])
suffix = ''.join(temp) # 将list类型转化成字符串类型
for _dir in os.listdir(dir):
if os.path.splitext(_dir)[-1] == suffix or os.path.isdir(dir + os.path.sep + _dir):
self.list.Append(_dir)
os.chdir(dir) # 设置工作路径
self.imagePath.SetLabel(os.getcwd())
def FileDialog(self, evt): # 打开文件对话框
wildcard = self.combobox.GetValue()
dialog = wx.FileDialog(None, "Choose a file", os.getcwd(), "", wildcard, wx.OPEN)
if dialog.ShowModal() == wx.ID_OK:
self.path = dialog.GetPath()
dialog.Destroy()
self.imagePath.SetLabel(self.path)
tempBitmap = wx.Image(self.path, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap.SetBitmap(tempBitmap)
self.bitmap.SetSize((580, 450))
def Back(self, evt):
pathInformation = os.path.split(self.imagePath.GetLabel())
self.imagePath.SetLabel(pathInformation[0])
os.chdir(pathInformation[0])
self.LoadDir(pathInformation[0])
def Ok(self, event):
path = self.imagePath.GetLabel()
self.GetParent().imagePath.SetLabel(path)
tempBitmap = wx.Image(path, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.GetParent().bitmap.SetSize((tempBitmap.GetWidth(), tempBitmap.GetHeight()))
self.GetParent().bitmap.SetBitmap(tempBitmap)
self.Destroy()
def Cancel(self, event):
self.Destroy()
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, u"第八次上机练习(WX)", size=(700, 700))
self.menuBar = wx.MenuBar()
self.file = wx.Menu()
self.file.Append(201, u"打开")
self.file.Append(202, u"下载验证码")
self.file.Append(203, u"保存")
self.file.Enable(203, False)
self.file.Append(204, u"退出")
self.Bind(wx.EVT_MENU_RANGE, self.FILE, id = 201, id2 = 204)
self.menuBar.Append(self.file, u"&文件")
self.ocr = wx.Menu()
self.ocr.Append(205, u"识别英文")
self.ocr.Append(206, u"识别中文")
self.Bind(wx.EVT_MENU_RANGE, self.OCR, id = 205, id2 = 206)
self.menuBar.Append(self.ocr, u"&OCR")
self.image = wx.Menu()
self.image.Append(207, u"图像增强")
self.Bind(wx.EVT_MENU, self.IMAGE, id = 207)
self.menuBar.Append(self.image, u"&图像")
self.about = wx.Menu()
self.about.Append(208, u"程序信息")
self.Bind(wx.EVT_MENU, self.ABOUT, id = 208)
self.menuBar.Append(self.about, u"&关于")
self.SetMenuBar(self.menuBar)
#self.panel = wx.Panel(self, -1)
self.text = wx.StaticText(self, -1, u" 图像文件:", pos=(0, 0), size=(70, 20))
self.imagePath = wx.StaticText(self, -1, u"None", pos=(70, 0), size=(100, 20))
self.identifyText = "" # 保存图像识别的结果
self.bitmap = wx.StaticBitmap(self, -1, pos = (5, 30))
def FILE(self, evt):
Id = evt.GetId()
if Id == 201: # 通过模式对话框选择图片
MyModalDialog(self, u"Image Browser").ShowModal()
elif Id == 202: # 下载验证码
url = 'https://portal1.ecnu.edu.cn/cas/Captcha.jpg' # 验证码生成页面的地址
imageData = urllib2.urlopen(url).read() # 读取验证码图片
f = open('identifyingCode.png','wb') # 打开一个identifyingCode.png文件,没有的话自动生成
f.write(imageData) # 写入图片内容
f.close() # 关闭文件
self.imagePath.SetLabel('D:\Canopy\User\Lib\site-packages\pytesser_v0.0.1\identifyingCode.png')
# 这里之所以把SetSize放在SetBitmap的前面,是因为这样可以让图片显示在左上角
tempBitmap = wx.Image('identifyingCode.png', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap.SetSize((tempBitmap.GetWidth(), tempBitmap.GetHeight()))
self.bitmap.SetBitmap(tempBitmap)
elif Id == 203: # 将识别结果保存成txt文件
wildcard = "Txt files (*.txt)|*.txt"
dialog = wx.FileDialog(None, "Save the file", "", "", wildcard, wx.SAVE)
if dialog.ShowModal() == wx.ID_OK:
self.path = dialog.GetPath()
file = open(self.path, 'wb')
file.write(self.identifyText)
file.close()
dialog.Destroy()
else: # 关闭窗口
self.Close()
def OCR(self, evt): # 图像识别
Id = evt.GetId()
if Id == 205:
path = self.imagePath.GetLabel()
image = Image.open(path)
self.identifyText = image_to_string(image)
wx.MessageBox(self.identifyText, u"TEXT")
self.file.Enable(203, True)
def IMAGE(self, evt): # 图像增强,将图片变为黑白
path = self.imagePath.GetLabel()
im = Image.open(path)
(w, h) = im.size
R = 0
G = 0
B = 0
for x in xrange(w):
for y in xrange(h):
pos = (x, y)
rgb = im.getpixel(pos)
(r, g, b) = rgb
R = R + r
G = G + g
B = B + b
rate1 = R * 1000 / (R + G + B)
rate2 = G * 1000 / (R + G + B)
rate3 = B * 1000 / (R + G + B)
for x in xrange(w):
for y in xrange(h):
pos = (x, y)
rgb = im.getpixel(pos)
(r, g, b) = rgb
n = r * rate1 / 1000 + g * rate2 / 1000 + b * rate3 / 1000
if n >= 60:
im.putpixel(pos, (255, 255, 255))
else:
im.putpixel( pos, (0, 0, 0))
im.save('D:\Canopy\User\Lib\site-packages\pytesser_v0.0.1\_temp\enhance.bmp') # 将增强后的图片副本保存在固定位置
wildcard = "bmp files (*.bmp)|*.bmp"
dialog = wx.FileDialog(None, "Save the file", "", "", wildcard, wx.SAVE)
if dialog.ShowModal() == wx.ID_OK:
self.path = dialog.GetPath()
dialog.Destroy()
im.save(self.path)
tempBitmap = wx.Image('D:\Canopy\User\Lib\site-packages\pytesser_v0.0.1\_temp\enhance.bmp', wx.BITMAP_TYPE_ANY).ConvertToBitmap() # 读取增强图片副本
self.bitmap.SetSize((tempBitmap.GetWidth(), tempBitmap.GetHeight()))
self.bitmap.SetBitmap(tempBitmap)
def ABOUT(self, evt): # 程序信息
wx.MessageBox(u"第八次上机练习(WX)\n图片转换成文本\n\n学号: 10152130110\n姓名: 李正甲",
u"Lab8", wx.OK | wx.ICON_INFORMATION, self)
if __name__=='__main__':
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show(True)
app.MainLoop()