利用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)

對字幕進行灰度處理,目的是使截取的字幕更加清晰。
如下效果:
裁剪視頻得到的圖片(其一):
在這裏插入圖片描述
截取字幕後:
在這裏插入圖片描述
進行灰度處理後
在這裏插入圖片描述
對於灰度處理,二值化處理不明白的可以參考如下文章。
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 KeySecret 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 KeySecret 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%的文字都提取到了還算可以哦。這次只是做了一個小小的練習,代碼還可以繼續優化,獲取到的字幕還能夠更加準確哦。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章