识别《冰与火》第一部的英语卡片 Part 2

第二步:测试部分英语卡片识别,生成一个排序列表

在第一步,我们用百度云普通识别出了单张图片的单词,今天我们需要测试识别少量的图片,并用pickle把单词和查询次数组成的字典归档,另外还要把卡片路径和它对应的单词组成的字典归档。第二个字典文件的键是卡片路径,值是单词,这样是因为路径是唯一的,同一个单词会有若干次查询,可能会有好几张图片,我们为了记录每张图片对应的路径才这样设置。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from aip import AipOcr
import os
import pickle


#文件夹中每张图片的绝对路径
def getthepicroot(rootpath):
rootcontent = os.walk(rootpath) #walk函数得到路径字符串,目录列表,文件列表组成的元组
for each in rootcontent:
folderroot = each[0] #目录字符串
folderpicroot = each[2] #文件列表
for every in folderpicroot:
if os.path.splitext(every)[1] == '.jpg':
picroot = ''.join([folderroot, '\\', every])
yield picroot #利用生成器导出每个文件的绝对路径


#百度图片识别得到每张图片的单词
def getwords(picroot):
APP_ID = '17896643'
API_KEY = 'V9MVA6nuN4h7nGPMaTWAGimE'
SECRET_KEY = 'OvTTuUWB1XXcWoh7kQ8OWDUAObvFReA5'
client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
with open(picroot, 'rb') as fp:
image = fp.read()
wordsinfo = client.basicGeneral(image)

wordsineed = wordsinfo['words_result']
englishwords = wordsineed[0]['words']
return englishwords


#主程序
quantity = 0 #用于计算单词出现的次数
try: #如果已经有统计单词出现次数的文件就直接读取
with open('E:\ICE AND FIRE\sumwords.pkl', 'rb') as f1:
sumwords = pickle.load(f1) #导出单词和他出现次数组成的字典

except: #如果没有就新建一个空的字典
sumwords = {}

try: #统计单词图片的绝对路径的文件
with open('E:\ICE AND FIRE\wordsroot.pkl', 'rb') as f3:
wordsroot = pickle.load(f3) #导出单词和他对应的绝对路径组成的字典

except:
wordsroot = {}



root = 'E:\ICE AND FIRE' #目标文件夹
pictureroot = getthepicroot(root) #产生图片绝对路径的生成器
for i in pictureroot:
if i not in wordsroot: #如果这个单词的路径(字典的键)还没有被统计过,注意这个字典的键是路径,键值是单词
words = getwords(i) #找到单词
print(words)

wordsroot[i] = words #再计入统计文件的字典

quantity += 1 #开始计算统计的单词的总个数
sumwords.setdefault(words, 0)#设置未出现的单词出现次数的初始值是0,如果已经出现过后面再赋值
sumwords[words] +=1 #不管是否出现过都增加一
if quantity%20 == 0: #为了防止网络中断等问题,只要统计到整二十的个数,就开始写入文件。
with open('E:\ICE AND FIRE\sumwords.pkl', 'wb') as f:
pickle.dump(sumwords, f)
with open('E:\ICE AND FIRE\wordsroot.pkl', 'wb') as f2:
pickle.dump(wordsroot, f2)
print('已经识别出了%d个单词。' % quantity)

#最后再写入一次文件是因为上面循环内在为了防止断网而采取的只要识别了20个就开始写入文件,但问题是如果单词
总个数的余数小于20的那一部分数据就没有写入文件,所以最后我们再次写入那一部分数据。
with open('E:\ICE AND FIRE\sumwords.pkl', 'wb') as f:
pickle.dump(sumwords, f)
with open('E:\ICE AND FIRE\wordsroot.pkl', 'wb') as f2:
pickle.dump(wordsroot, f2)
print('共完成了%d个单词的识别。' % quantity)

listsort = sorted(sumwords.items(), key=lambda x:x[1], reverse=True) #把sumwords列表排序, sorted函数第一参数是统计单词和次数的元组组成的列表,第二个参数是排序的规则及按照每个元组第二个元素及次数大小,第三个参数是指按照倒序(reverse=True)
listsorted = [i for i in listsort if i[1]>=4] #运用列表解析式找到出现过四次及以上次数的单词,这段代码在用于测试少量图片时可以改为‘>=1', 只要有一次出现都会列表出来。
print(listsorted)

测试文件共81个

测试得到的列表:

我们可以看到识别出了共81张图片,以及所有单词和查询次数的汇总,还有生成的两个二进制文件,sumwords储存着单词和对应的次数,wordsroot是存着绝对路径和对应的单词。但是我们可以看到,里面有些单词只有一个单字母或者很奇怪的单词如:(‘g’, 1), (‘b’, 1), (‘grIp’, 1). 很明显这是因为普通识别不能很精确的识别一些图片导致的,虽然我们在第一步里面也看到精确识别的问题,但是总体上来说精确还是更优势一些。但我们的问题又来了,百度云里面对于免费用户来说,精确识别的服务只有每天500次,对于还算有点庞大的数据来说根本不够啊。

开通的价格对于我们这种底层玩家来说太贵了,我想两本书下来就有差不多一万张图片了。

所以呢我们只有先用普通识别出绝大多数的单词后,再挑出其中未被准确识别的单词和他对应路径,再通过精确识别识别出来就可以了,每天500次就够了。第三步我们就做这个工作。

未完待续。。。。