我的CSDN部落格id:qq_39783601,昵稱是糖潮麗子~辣麗
從今天開始我會陸續将資料分析師相關的知識點分享在這裡,包括Python、機器學習、資料庫等等。
今天來分享一個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)
對字幕進行灰階處理,目的是使截取的字幕更加清晰。
如下效果:
裁剪視訊得到的圖檔(其一):
截取字幕後:
進行灰階處理後:
對于灰階處理,二值化處理不明白的可以參考如下文章。
通路百度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。
複制下面連結到浏覽器:
替換對應如下的内容,就是上面建立應用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%的文字都提取到了還算可以哦。這次隻是做了一個小小的練習,代碼還可以繼續優化,擷取到的字幕還能夠更加準确哦。