如何提高英语的词汇量
事情的起因是这样的,某天闲逛B站的时候看到一个视频:链接: 800有趣句子背完7000单词.我一看,还有这等操作?一下子感觉英语容易了许多,点开一看
这文字,这字体,oh shit,太工整了。一看时长,两个多小时,立马收藏,看了十来句,我就进入了梦乡,啊这,看视频学习的难度太高了,我就萌生了把这800句搞下来的想法,于是乎,有了这篇文章。
第一步 获取视频中的可用帧
以我现在的知识储备,首先想到的最容易获取文本的,就是文字识别,文字识别之前,自然是要获取带有文字的图片,再通过图片获取文本信息。
获取视频中某一帧的图片,这里就使用OpenCV来截取视频中的帧。
按照视频的信息来看,这个视频是 25帧/秒 的,需要恰到好处的截取
通过视频中的时间和当前的句子序号,基本可以确定,这个视频句子序号和时间就是线性关系。这是我用手点出来的,肯定存在一定的误差
lista = []
for i in range(1000):
list1 = lists[random.randint(0,4)]
list2 = lists[random.randint(0,4)]
while(list1 == list2):
list2 = lists[random.randint(0,4)]
#print(list1,list2)
a = (list1[0]-list2[0])/(list1[1]-list2[1])
lista.append(a)
print(lista)
max = 0
min = 100
for per in lista:
if(max<per):
max = per
if(min>per):
min = per
print(min,max)
经过对五个数据反复运算,最小值和最大值如下
10.581818181818182 11.0
说明每个句子时长在10.5s左右,每秒25帧,就是,每句存在262帧,视频p1的总时长4265s,400句,每句10.6625s,看来差不多,其实这种方法并没有多大卵用。
camera = cv2.VideoCapture(videoname)
dict = 0
index = 50
while True:
res,image = camera.read()
dict+=1
if not res:
print('啥都没有')
break
if res == True and dict == int(((index-1)*10.6625+5.33125)*25):
cv2.imshow("window",image)
cv2.waitKey()
使用上述代码可以显示某一帧,按照每个句子存在的时间,算出当前句子存在哪一帧。
这是第50个句子,和index一样,说明计算方法没有错。(这种视频太大了,遍历非常耗费时间)
现在图片已经获取到了,下面就是要提取图中的文本信息。
第二步 获取图像中的文本信息
要获取文本,就要进行图像识别,这里使用百度(白嫖)OCR来识别图像中的数据,由于camera.read()读取的图像无法识别,所以这里曲线救国,使用cv2.imwrite保存为图片,再读取进行图像识别
APP_ID = '******'
API_KEY = '******'
SECRET_KEY = '******'
apiOcr = AipOcr(APP_ID,API_KEY,SECRET_KEY)
videoname = "F:\CODE\Pycode\800\Source\\800有趣句子背完7000单词1.mp4"
camera = cv2.VideoCapture(videoname)
dict = 0
index = 1
while True:
res,image = camera.read()
dict+=1
if not res:
print('啥都没有')
break
if res == True and dict == int(((index-1)*10.6625+5.33125)*25):
cv2.imshow("window",image)
cv2.imwrite('F:/CODE/Pycode/800/Source//temp.jpg',image)
with open('F:\CODE\Pycode\800\Source\\temp.jpg','rb') as fp:
img = fp.read()
result = apiOcr.basicGeneral(img)
print(result)
cv2.waitKey()
上面的代码中,result = apiOcr.basicGeneral(img) 读取图像并返回一个字典。
{'words_result': [{'words': 'With my own ears I clearly heard the heart beat of'}, {'words': 'the nuclear bomb'}, {'words': '我亲耳清楚地听到原子弹的心脏的跳动。'}], 'log_id': 1314957837251641344, 'words_result_num': 3}
这是第一帧图像的文本数据,很明显,序号并没有识别到,因为1本身太小了,英文的结束符也没有识别到,句号倒是识别出来了。值得一提的是,With的首字母大写是正确识别了的,得益于视频本身的清晰质量,识别出来的结果针不戳。这一次识别没有识别出序号,但是序号为三位数时,就很容易识别出来,所以要对结果进行处理,存储到文本文件中去。
返回的数据中,除了words之外,还有一个ID,一个num,num应该指的是识别出来的文本有几段,ID应该可以在多线程请求时用来排序。
这是获取的文本结果,很明显,因为序号太小,所以只有部分序号被识别出来。而且很明显,有部分句子是没有获取到的,所以并不是每条句子都是相同的时间间隔。解决方案也有,就是在识别出来后与上一句句子进行对比,相同就后移一小段。那时间间隔就要重新确定,按照采样原理,有效的数据有400份,那想要不失真,就要采集八百个点以上(这是啥定理来着,忘了),那就5秒采一个帧,识别出来内容相同就舍弃。
camera = cv2.VideoCapture(videoname)
dict = 0
index = 1
point = 5*25
preword = ""
while True:
res,image = camera.read()
dict+=1
if not res:
print('啥都没有')
break
if res == True and dict == point:
#cv2.imshow("window",image)
cv2.imwrite('F:/CODE/Pycode/800/Source//temp.jpg',image)
with open('F:\CODE\Pycode\800\Source\\temp.jpg','rb') as fp:
img = fp.read()
point += 5*25 #下一个读取点
result = apiOcr.basicGeneral(img)
#print(result)
word = result['words_result']
if word == preword: #用来判断当前句子与上一句是否相同,相同就下一个采样点再检测
continue
preword = word
strs = ''
for per in range(len(word)):
strs += word[per]['words']+" "
with open(txtpath,'a',encoding = 'utf-8') as txtfp:
txtfp.write(str(index)+" "+strs+'\n')
#print(strs+'\n')
print("第%d帧已写入文件"%(index))
index+=1
很明显,行不通,因为句号和逗号有时候能识别待,而有时候又看不见,不能搞整体识别,应该搞一个局部识别。由于序号有时候能识别,有时候又不能识别,那就截取其中一部分来对比,虽然不一定完全准确,但出现重复的几率要小很多。
if preword[5:20].strip(",' ") in str(word).strip(",' "):
continue
preword = str(word)
值得注意的是preword本身需要赋值,且一定要超过20个字符,否则由于空字符包含在任何字符串中,导致程序一直continue。
emmm,差强人意。一顿操作猛如虎,最后还是不如先把数据弄下来再处理。
有趣的一点是:我想通过不断重设读取的起始位置来加快读取速度,这样又很容易接受不到图像识别的结果,算了,只有800句而已。
看来还是有三个漏网之鱼,不过无所谓了。
第三步 写一个小的APP来更快的学习
<TextView
android:id="@+id/CNview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:selectAllOnFocus="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ENView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:selectAllOnFocus="true"
app:layout_constraintBottom_toBottomOf="@id/CNview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints" />
整两个布局来分别显示中文和英文。
CNview.setOnClickListener{
var random = (0..802).random()
ENView.setText(enarray[random])
CNview.setText(cnarray[random])
}
用一个简单的点击事件来切换
难看是难看了点,不过,这样就能提高词汇量了(一定是这样的没错),好的,该玩游戏了。