天天看點

python視訊處理字幕_利用Python提取視訊中的字幕(文字識别)

我的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%的文字都提取到了還算可以哦。這次隻是做了一個小小的練習,代碼還可以繼續優化,擷取到的字幕還能夠更加準确哦。