wxPython:调用OCR模块实现图片识别

(读者电脑中应安装有Canopy)

先下载tesseract-ocr模块:OCR模块

将其安装在Canopy那个盘。

安装了之后,下载代码:代码

将代码解压至......\Canopy\User\Lib\site-packages

然后在Canopy内运行代码文件中的pytesser.py即可。

PS:

  1. 要将代码中11,237,301,311行的路径修改成读者本机路径。
  2. 代码中抓取的图片地址为华东师范大学公共数据库

# -*- coding: utf-8 -*-import os
import wx
import util
import errors
import urllib2
import subprocess
from PIL import Imageos.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 operationdef 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 textdef 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:raisefinally:if cleanup:util.perform_cleanup(scratch_image_name, scratch_text_name_root)return textclass 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)  # 文件夹listboxself.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()




本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部