學了好久機器學習的內容有些許枯燥,今天我們來做一個Python的小項目來玩耍吧!
項目背景
通過獲取百度API實現視頻文字識別。
需求闡述
將.MP4格式視頻裁剪成一幀一幀的圖片再將圖片中的字幕摘取出來,保存成一個文檔。
進入正題嘍!!!
思路
1.將視頻按幀截取成圖片
2.將上一步截取的圖片再進行裁剪,只保留字幕部分,然後在進行灰度處理
3.調用百度api識別文字
4.輸出成txt
首先導包
# base64是一種將不可見字符轉換爲可見字符的編碼方式
import base64
# opencv是跨平臺計算機視覺庫,實現了圖像處理和計算機視覺方面的很多通用算法
import os
import cv2
import requests
from aip import AipOcr
# 百度AI的文字識別庫
base64
base64是一種將不可見字符轉換爲可見字符的編碼方式。
opencv
是跨平臺計算機視覺庫,實現了圖像處理和計算機視覺方面的很多通用算法。
AipOcr
百度AI的文字識別庫。
注意:
這裏from aip import AipOcr
剛開始可能會報錯,原因可能是aip和baidu-aip根本不是同一個包,如果想要import的時候,都是使用:import aip
之後pip install baidu-aip就沒報錯了。
代碼詳情
裁剪視頻
def tailor_video():
# 要提取視頻的文件名,隱藏後綴
sourceFileName = 'material'
# 在這裏把後綴接上
video_path = os.path.join("G:/material/", sourceFileName + '.mp4')
times = 0
# 提取視頻的頻率,每10幀提取一個
frameFrequency = 10
# 輸出圖片到當前目錄video文件夾下
outPutDirName = 'G:/material/video/' + sourceFileName + '/'
if not os.path.exists(outPutDirName):
# 如果文件目錄不存在則創建目錄
os.makedirs(outPutDirName)
camera = cv2.VideoCapture(video_path)
while True:
times += 1
res, image = camera.read()
if not res:
print('not res , not image')
break
if times % frameFrequency == 0:
cv2.imwrite(outPutDirName + str(times) + '.jpg', image) #文件目錄下將輸出的圖片名字命名爲10.jpg這種形式
print(outPutDirName + str(times) + '.jpg')
print('圖片提取結束')
這裏定義一個函數用來裁剪視頻。
我們需要將視頻裁剪成一幀一幀的圖片,將圖片保存成10.jpg這種形式,並且將這些裁剪後的圖片放在一個目錄下。
這裏我設置的是每10幀裁剪一張,你也可以任意設置多少幀裁剪。
視頻裁剪後的圖片效果:
創建文本
def text_create(name, msg):
desktop_path = "G:/material/" # 新創建的txt文件的存放路徑
full_path = desktop_path + name + '.txt' # 也可以創建一個.doc的word文檔
file = open(full_path, 'w')
file.write(msg)
file.close()
這裏創建一個函數,用來存放提取後的文字信息。
創建.txt文本存放提取後的文字。
判斷中文
# 定義一個函數,用來判斷是否是中文,是中文的話就返回True代表要提取中文字幕
def is_Chinese(word):
for ch in word:
if '\u4e00' <= ch <= '\u9fff':
return True
return False
定義一個函數,用來判斷是否是中文,是中文的話就返回True代表要提取中文字幕,不是中文的就返回False。
截取字幕
def tailor(path1,path2,begin,end,step_size): #截取字幕
for i in range(begin,end,step_size):
fname1=path1 % str(i)
print(fname1)
img = cv2.imread(fname1)
print(img.shape)
cropped = img[500:600, 100:750] # 裁剪座標爲[y0:y1, x0:x1]
imgray = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY)
thresh = 200
ret, binary = cv2.threshold(imgray, thresh, 255, cv2.THRESH_BINARY) # 輸入灰度圖,輸出二值圖
binary1 = cv2.bitwise_not(binary) # 取反
cv2.imwrite(path2 % str(i), binary1)
對字幕進行灰度處理,目的是使截取的字幕更加清晰。
如下效果:
裁剪視頻得到的圖片(其一):
截取字幕後:
進行灰度處理後
對於灰度處理,二值化處理不明白的可以參考如下文章。
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/threshold/threshold.html
https://blog.csdn.net/qq_37385726/article/details/82015545
訪問百度API
# 定義一個函數,用來訪問百度API,
def requestApi(img):
request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"
params = {"image": img,'language_type':'CHN_ENG'}
access_token = '24.b802cd212b0e702b018f999c594b6d9f.2592000.1589466832.282335-19430506'
request_url = request_url + "?access_token=" + access_token
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
results=response.json()
return results
這裏的access_token
是這麼來的:
首先你需要百度搜索:百度ocr—— 點擊文字識別
第二步:點擊立即使用
第三步:創建應用
第四步:隨便填寫一個名稱,然後立即創建。
創建成功後你就會看到你剛纔創建的一個應用test。
此時,我們需要這裏的API Key
和Secret Key
兩個參數中的內容,用來獲取access_token
的內容。
接下來第五步點擊技術文檔
第六步:點擊通用文字識別
這裏有access_token相關的介紹,可以點擊Access Token獲取查看詳情。
詳情介紹瞭如何獲取Access Token。
複製下面鏈接到瀏覽器:
https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=Va5yQRHlA4Fq5eR3LT0vuXV4&client_secret=0rDSjzQ20XUj5itV6WRtznPQSzr5pVw2&
替換對應如下的內容,就是上面創建應用test後得到的API Key
和Secret Key
兩個參數中的內容,對應替換。
替換後回車就會得到:access Token的值。
其他代碼中剩餘的參數可以自行設置。
讀取圖片&字幕操作
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
# 將讀取出來的圖片轉換爲b64encode編碼格式
return base64.b64encode(fp.read())
# 定義函數字幕,用來對字幕進行操作
# step_size 步長
def subtitle(fname,begin,end,step_size):
array =[] #定義一個數組用來存放words
for i in range(begin,end,step_size): #begin開始,end結束,循環按照步長step_size遍歷,共有419張圖片,也就是(1,420,10)
fname1=fname % str(i)
print(fname1)
image = get_file_content(fname1)
try:
results=requestApi(image)['words_result'] #調用requestApi函數,獲取json字符串中的words_result
for item in results:
print(results)
if is_Chinese(item['words']):
array.append(item['words'].replace('獵奇筆記本', '')) # 將圖片中不需要的字幕“獵奇筆記本”替換爲空
except Exception as e:
print(e)
text=''
result = list(set(array)) # 將array數組準換爲一個無序不重複元素集達到去重的效果,再轉爲列表
result.sort(key=array.index) # 利用sort將數組中的元素即字幕重新排序,達到視頻播放字幕的順序
for item in result:
print(item)
text+=item+'\n'
text_create('test1',text)
首先需要對讀取到的圖片進行轉碼,轉爲b64encode編碼格式。
其中,在圖片識別時候可能會識別到除字幕外的文字,我們還需要將圖片中不需要的文字替換爲空,只獲取字幕。
例如:此處我們需要將“獵奇筆記本”替換爲空。
主方法控制檯輸出運行
if __name__ =="__main__":
path1 = 'G:/material/video/img/%s.jpg' # 視頻轉爲圖片存放的路徑(幀)
path2 = 'G:/material/video/img2/%s.jpg' # 圖片截取字幕後存放的路徑
print("""
1.圖片裁剪
2.提取字幕
3.裁剪視頻
""")
choose=input()
begin=100
end=1000
step_size=10
if choose=='1':
tailor(path1,path2,begin,end,step_size)
if choose=='2':
subtitle(path2,begin,end,step_size)
if choose=='3':
tailor_video()
結果:
結果中精確度還不是很高,不過80%的文字都提取到了還算可以哦。這次只是做了一個小小的練習,代碼還可以繼續優化,獲取到的字幕還能夠更加準確哦。