示例简介
python利用百度文字识别功能,实现对上传的名片进行扫描,并获取名片信息;可查看名片原图,也可以保存信息到Excel。
开发环境:Windows7+python3.7+pycharm2018.2.4(开发工具);
目录机构:
最终效果:
百度端创建应用
创建过程参考《微信小程序利用百度AI实现扫描身份证获取信息功能》(把“图像识别”换为“文字识别”)。
实现过程
一、阅读器UI设计
1. 安装模块和配置工具,参考《python实现小说阅读器》;
2. 运行工具QtDesigner,利用QtDesigner工具箱设计出界面效果(所需要的控件可查看右边区域),保存效果为文件bc.ui;
3. 对文件bc.ui执行pyUIC(ui转化为py代码),执行完生成文件bc.py。
二、代码设计
1. 新建文件bc_main.py,该文件为项目主文件,初始化页面并显示;
2. 添加内置模块(下面代码使用)和主方法(用于运行后弹出界面);
Tips:由于是引入bc(bc.py),而未对其修改,所以开发过程中可以随时修改设计重新生成bc.py,不会覆盖掉自己编写的代码;但要注意如果修改了表单属性和名称等,编写的代码要跟着修改;
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
# 引入自定义模块
import bc
# 引入内置模块
import sys
import os
# 引入第三方模块
import pandas as pd
import requests, base64
from PIL import Image
import phone
# 文字识别sdk所需要模块
from aip import AipOcr
class parentWindow(QWidget,bc.Ui_Form):
# 初始化方法
def __init__(self):
# 找到父类 首页面
super(parentWindow, self).__init__()
# 初始化页面方法
self.setupUi(self)
# 点击选择名片
self.selectCard.clicked.connect(self.openfile)
# 点击查看名片
self.viewButton.clicked.connect(self.viewbtn)
# 点击保存按钮
self.saveButton.clicked.connect(self.saveData)
if __name__=='__main__':
# 每一个PyQt5应用都必须创建一个应用对象
app=QApplication(sys.argv)
# 初始化页面
window=parentWindow()
# 显示首页
window.show()
sys.exit(app.exec_())
3. 添加公共代码,用来判断“名片信息表.xlsx”是否存在,不存在则新建该文件并定义好列名;
# 获取当前路径
cdir = os.getcwd()
# 文件路径
path = cdir+'/名片信息表.xlsx'
# 读取路径 判断是否创建了文件
if not os.path.exists(path):
# 根据路径建立文件夹
# os.makedirs(path)
# 姓名 手机 电话 邮箱 网址 公司 地址 城市
cardfile = pd.DataFrame(columns=['name', 'mobile', 'tel', 'email', 'url', 'comp', 'addr', 'city'])
# 生成xlsx文件
cardfile.to_excel(path, sheet_name='data', index=None)
4. 添加图片识别函数recgImg,用来扫描图片获取图片信息;而文字识别百度给了两种方法选择,一种使用API(本文使用),详细参考https://cloud.baidu.com/doc/OCR/s/5k3h7xyi2;另一种是使用SDK,详细参考https://cloud.baidu.com/doc/OCR/s/5k3h7xyi2
# 识别名片图片
def recgImg(self):
# 获取baiduToken
apikey = '你的apikey'
seckey = '你的seckey'
tokenUrl = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + apiKey + '&client_secret=' + seckey
res = requests.get(url=tokenUrl, headers={'content-type': 'application/json; charset=UTF-8'}).json()
baiduToken = res['access_token']
'''
名片识别(API)
'''
request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_card"
# 二进制方式打开图片文件
f = open(self.download_path[0], 'rb')
img = base64.b64encode(f.read())
params = {"image": img}
# access_token = '[调用鉴权接口获取的token]'
request_url = request_url + "?access_token=" + baiduToken
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
if response:
print(response.json())
return response.json()
# """ 你的 APPID AK SK(SDK) """
# APP_ID = '你的APP_ID'
# API_KEY = '你的API_KEY'
# SECRET_KEY = '你的SECRET_KEY'
#
# client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
# """ 读取图片 """
# def get_file_content(filePath):
# with open(filePath, 'rb') as fp:
# return fp.read()
#
# image = get_file_content(self.download_path[0])
#
# """ 如果有可选参数 """
# options = {}
# options["language_type"] = "CHN_ENG"
# options["detect_direction"] = "true"
# options["detect_language"] = "true"
# options["probability"] = "false"
#
# """ 调用api"""
# picture_result = client.basicAccurate(image, options) # 返回识别结果
# words_result = picture_result['words_result']
# print(words_result)
# return words_result
5. 实现点击“选择名片”功能,用来扫描选择的名片,并把名片和获取到的名片信息显示到界面;
# 选择名片按钮执行方法
def openfile(self):
# 启动选择文件对话空,查找jpg以及png图片
self.download_path = QFileDialog.getOpenFileName(self, "选择要识别的图片", os.getcwd(), "Image Files(*.jpg *.png)")
# 判断是否选择图片
if not self.download_path[0].strip():
QMessageBox.information(self, '提示信息', '没有选择名片图片')
pass
else:
# pixmap解析图片
pixmap = QPixmap(self.download_path[0])
# 设置图片
self.imgLable.setPixmap(pixmap)
# 让图片自适应label大小
self.imgLable.setScaledContents(True)
try:
# 识别名片图片返回识别结果
content = self.recgImg()
except:
QMessageBox.information(self, '提示信息', '识别错误请重新选择图片')
# 识别图片的数据赋值
words_result = content['words_result']
for key in words_result:
textValue = words_result[key][0]
if key == 'NAME':
self.usLineEdit.setText(textValue)
elif key == 'MOBILE':
self.phoneLineEdit.setText(textValue)
elif key == 'TEL':
self.telLineEdit.setText(textValue)
elif key == 'EMAIL':
self.emailLineEdit.setText(textValue)
elif key == 'URL':
self.urlLineEdit.setText(textValue)
elif key == 'COMPANY':
self.companyLineEdit.setText(textValue)
elif key == 'ADDR':
self.addrLineEdit.setText(textValue)
6. 实现点击“查看名片”功能,用来全屏显示名片图片;
# 点击查看名片显示大图功能
def viewbtn(self):
if self.download_path:
# 使用电脑中的看图工具打开图片
img = Image.open(self.download_path[0])
# 显示图片
img.show()
else:
QMessageBox.information(self, '提示信息', '先选择名片图片')
7. 添加公共函数clearCardData,用来在保存成功后清除图片和名片信息;
# 清理名片数据
def clearCardData(self):
# 去掉历史图片路径
self.download_path = ''
# 移除控件上图片
self.imgLable.setPixmap(QPixmap(""))
# 移除输入框内容
self.usLineEdit.setText("")
self.phoneLineEdit.setText("")
self.telLineEdit.setText("")
self.emailLineEdit.setText("")
self.urlLineEdit.setText("")
self.companyLineEdit.setText("")
self.addrLineEdit.setText("")
8. 实现点击“保存”功能,用来把获取的信息保存到Excel;
# 保存名片信息到文档
def saveData(self):
pi_table = pd.read_excel(path, sheet_name='data')
# 获取输出框内容
name = self.usLineEdit.text()
mobile = self.phoneLineEdit.text()
tel = self.telLineEdit.text()
email = self.emailLineEdit.text()
url = self.urlLineEdit.text()
comp = self.companyLineEdit.text()
addr = self.addrLineEdit.text()
# 判断手机号是否为空
if mobile.strip():
# 根据手机号判断区域
try:
info = phone.Phone().find(int(mobile))
except Exception as e:
QMessageBox.critical(self, "错误:", "手机号码不正确!", QMessageBox.Ok) # 弹出提示对话框
self.phoneLineEdit.setFocus() # 让手机文本框获得焦点
return
# 判断手机号是否正确返回信息
if info == None:
city = '其他'
else:
# 正确返回信息获取省
city = info['province']
else:
city = '其他'
# 判断姓名是否为空
if name.strip():
# 添加数据
data = pi_table.append({'name': name,
'mobile': mobile,
'tel': tel,
'email': email,
'url': url,
'comp': comp,
'addr': addr,
'city': city,
}, ignore_index=True)
# 更新xlsx文件
pd.DataFrame(data).to_excel(path, sheet_name='data', index=False)
# 保存成功
QMessageBox.information(self, '提示信息', '保存成功')
self.clearCardData()
else:
QMessageBox.information(self, '提示信息', '姓名不能为空')
pass
9. 最终合并代码:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
# 引入自定义模块
import bc
# 引入内置模块
import sys
import os
# 引入第三方模块
import pandas as pd
import requests, base64
from PIL import Image
import phone
# 文字识别sdk所需要的模块
from aip import AipOcr
# 获取当前路径
cdir = os.getcwd()
# 文件路径
path = cdir+'/名片信息表.xlsx'
# 读取路径 判断是否创建了文件
if not os.path.exists(path):
# 根据路径建立文件夹
# os.makedirs(path)
# 姓名 手机 电话 邮箱 网址 公司 地址 城市
cardfile = pd.DataFrame(columns=['name', 'mobile', 'tel', 'email', 'url', 'comp', 'addr', 'city'])
# 生成xlsx文件
cardfile.to_excel(path, sheet_name='data', index=None)
class parentWindow(QWidget,bc.Ui_Form):
# 初始化方法
def __init__(self):
# 找到父类 首页面
super(parentWindow, self).__init__()
# 初始化页面方法
self.setupUi(self)
# 点击选择名片
self.selectCard.clicked.connect(self.openfile)
# 点击查看名片
self.viewButton.clicked.connect(self.viewbtn)
# 点击保存按钮
self.saveButton.clicked.connect(self.saveData)
#选择名片按钮执行方法
def openfile(self):
# 启动选择文件对话空,查找jpg以及png图片
self.download_path = QFileDialog.getOpenFileName(self, "选择要识别的图片", os.getcwd(), "Image Files(*.jpg *.png)")
# 判断是否选择图片
if not self.download_path[0].strip():
QMessageBox.information(self, '提示信息', '没有选择名片图片')
pass
else:
# pixmap解析图片
pixmap = QPixmap(self.download_path[0])
# 设置图片
self.imgLable.setPixmap(pixmap)
# 让图片自适应label大小
self.imgLable.setScaledContents(True)
try:
# 识别名片图片返回识别结果
content=self.recgImg()
except:
QMessageBox.information(self, '提示信息', '识别错误请重新选择图片')
# 识别图片的数据赋值
words_result = content['words_result']
for key in words_result:
textValue = words_result[key][0]
if key == 'NAME':
self.usLineEdit.setText(textValue)
elif key == 'MOBILE':
self.phoneLineEdit.setText(textValue)
elif key == 'TEL':
self.telLineEdit.setText(textValue)
elif key == 'EMAIL':
self.emailLineEdit.setText(textValue)
elif key == 'URL':
self.urlLineEdit.setText(textValue)
elif key == 'COMPANY':
self.companyLineEdit.setText(textValue)
elif key == 'ADDR':
self.addrLineEdit.setText(textValue)
# 识别名片图片
def recgImg(self):
# 获取baiduToken
apikey = '你的apikey'
seckey = '你的seckey'
tokenUrl = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+apikey+'&client_secret='+seckey
res = requests.get(url=tokenUrl, headers={'content-type': 'application/json; charset=UTF-8'}).json()
baiduToken = res['access_token']
'''
名片识别(API)
'''
request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_card"
# 二进制方式打开图片文件
f = open(self.download_path[0], 'rb')
img = base64.b64encode(f.read())
params = {"image": img}
# access_token = '[调用鉴权接口获取的token]'
request_url = request_url + "?access_token=" + baiduToken
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
if response:
print(response.json())
return response.json()
# """ 你的 APPID AK SK(SDK) """
# APP_ID = '你的APP_ID'
# API_KEY = '你的API_KEY'
# SECRET_KEY = '你的SECRET_KEY'
#
# client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
# """ 读取图片 """
# def get_file_content(filePath):
# with open(filePath, 'rb') as fp:
# return fp.read()
#
# image = get_file_content(self.download_path[0])
#
# """ 如果有可选参数 """
# options = {}
# options["language_type"] = "CHN_ENG"
# options["detect_direction"] = "true"
# options["detect_language"] = "true"
# options["probability"] = "false"
#
# """ 调用api"""
# picture_result = client.basicAccurate(image, options) # 返回识别结果
# words_result = picture_result['words_result']
# print(words_result)
# return words_result
# 点击查看名片显示大图功能
def viewbtn(self):
if self.download_path:
# 使用电脑中的看图工具打开图片
img = Image.open(self.download_path[0])
# 显示图片
img.show()
else:
QMessageBox.information(self, '提示信息', '先选择名片图片')
# 保存名片信息到文档
def saveData(self):
pi_table = pd.read_excel(path, sheet_name='data')
# 获取输出框内容
name =self.usLineEdit.text()
mobile = self.phoneLineEdit.text()
tel = self.telLineEdit.text()
email = self.emailLineEdit.text()
url = self.urlLineEdit.text()
comp = self.companyLineEdit.text()
addr = self.addrLineEdit.text()
# 判断手机号是否为空
if mobile.strip():
# 根据手机号判断区域
try:
info = phone.Phone().find(int(mobile))
except Exception as e:
QMessageBox.critical(self,"错误:","手机号码不正确!",QMessageBox.Ok) # 弹出提示对话框
self.phoneLineEdit.setFocus() # 让手机文本框获得焦点
return
# 判断手机号是否正确返回信息
if info==None:
city = '其他'
else:
# 正确返回信息获取省
city = info['province']
else:
city = '其他'
# 判断姓名是否为空
if name.strip():
# 添加数据
data = pi_table.append({'name': name,
'mobile': mobile,
'tel': tel,
'email': email,
'url': url,
'comp': comp,
'addr': addr,
'city': city,
}, ignore_index=True)
# 更新xlsx文件
pd.DataFrame(data).to_excel(path, sheet_name='data', index=False)
# 保存成功
QMessageBox.information(self, '提示信息', '保存成功')
self.clearCardData()
else:
QMessageBox.information(self, '提示信息', '姓名不能为空')
pass
# 清理名片数据
def clearCardData(self):
# 去掉历史图片路径
self.download_path = ''
# 移除控件上图片
self.imgLable.setPixmap(QPixmap(""))
# 移除输入框内容
self.usLineEdit.setText("")
self.phoneLineEdit.setText("")
self.telLineEdit.setText("")
self.emailLineEdit.setText("")
self.urlLineEdit.setText("")
self.companyLineEdit.setText("")
self.addrLineEdit.setText("")
if __name__=='__main__':
# 每一个PyQt5应用都必须创建一个应用对象
app=QApplication(sys.argv)
# 初始化页面
window=parentWindow()
# 显示首页
window.show()
sys.exit(app.exec_())
最后结语
本文利用python+百度文字识别,实现上传名片的扫描,并把图片和获取的信息显示到界面,可点击“查看名片”全屏浏览图片,也可点击“保存”,把信息保存到Excel。
扫描公众号,了解更多实例分享