獲取監控視頻圖像幀的時間戳


背景:

我們采集了一系列的監控視頻,視頻的左上角會實時顯示時間。通過python opencv庫,我們可以從視頻中截取視頻幀,目標是獲取每一幀的時間戳(Unix時間戳)。

基於這樣的背景,我們的解決方案逐漸進行了優化。

粗糙的方案——估算時間戳

讀取視頻第一幀的時間戳,可以觀看視頻起始幀的時間,將其轉換為unix時間戳,然后根據幀率計算接下來幀的時間戳。

舉個例子:

image-20210907221604896

上面為視頻的第一幀的時間,我們將其轉為對應的時間戳(轉換方式可以自行搜索)為1615889100。之后,我們可以根據幀率來估計每隔多少幀,時間戳會+1,給對應幀標上對應的時間戳。

例如我們的視頻幀率為30fps,那么每隔30幀,時間上加1秒,時間戳+1即可。

精細的方案——tessoract進行數字識別(python接口)

上面粗糙的方案會出現問題,我們的視頻中間可能由丟幀的情況,通過計算得到的視頻幀時間戳難免出現偏差,並且這樣偏差會隨着視頻的長度累計,導致后面的時間戳計算出現更大的誤差。所以對該方案進行優化:

我們的優化方案為:截取視頻幀左上角的時間,通過OCR技術將其轉為時間字符串,再把時間換算為時間戳。

對於OCR工具,我們選擇了開源的tesseract,因為比較熟悉python,就使用了python封裝后的tesseract接口。

筆者最后選擇了tesserocr作為工具,進行識別,但是對於上面的圖片,我們直接進行識別,卻無法得到想要的結果,甚至識別不出內容。進行相應問題的搜索,有人在stackoverflow上提出了類似的問題:https://stackoverflow.com/questions/55994807/why-does-pytesseract-fail-to-recognise-digits-from-image-with-darker-background(無法從背景較暗的圖形中識別出數字)

按照鏈接中的方法,進行了灰度轉換,以及圖像二值化,最后得到的圖像結果類似下面的效果:

image-20210907223254970

理論上來說,這樣的圖像已經很清晰了,識別應該相當准確才對,但實際上,還是出現了數字識別錯誤的問題,並且還比較頻繁。之后繼續進行檢索,在https://www.pythonf.cn/read/84263博客中看到,tesseract做圖像識別時需要白底黑字,所以我們得到的黑底白字圖像,要做最后的像素轉換:最終得到的效果為:

image-20210907230144594

再拿去做識別,得到的結果就相當准確了!

最后附上進行ocr識別以及時間戳轉換的代碼,讀者可以參考里面的函數進行自己的實現:

from PIL import Image
import cv2
import tesserocr 
import time

def binarization_file(time_img_file,black_font=False):
    '''
    description:將指定的圖像二值化 
    param {time_img_file:輸入的圖像,圖像文件xxx.jpg;black_font:把黑底白字轉為白底黑字}
    return {time_bin_img:二值化后的圖像,Image對象}
    '''    
    # cv2進行讀取
    img = cv2.imread(time_img_file)
    # If your image is not already grayscale :
    # img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 進行二值化
    threshold = 180 # to be determined
    _, img_binarized = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
    # 對二值圖像進行像素反轉
    if(black_font):
        img_binarized = 255-img_binarized
    # 轉為Image類型
    time_bin_img = Image.fromarray(img_binarized)
    return time_bin_img

def ocr(time_bin_img):
    '''
    description:對二值圖像進行OCR識別 
    param {time_bin_img:二值化后的圖像,Image對象}
    return {text:識別出的字符串,取[:-1]是為了去掉換行符,replace函數用於刪除其中的空格}
    '''    
    text = tesserocr.image_to_text(time_bin_img)
    return text[:-1].replace(" ","")
    
def time2timestamp(time_str):
    '''
    description:將時間格式的字符串轉為時間戳 
    param {time_text:時間格式的字符串,格式為:'2019-06-03 21:19:03'}
    return {time_stamp:時間戳,整數類型}
    '''    
    time_array = time.strptime(time_str,"%Y-%m-%d %H:%M:%S")
    time_stamp = int(time.mktime(time_array))
    return time_stamp

if __name__=="__main__":
    pic = "test.jpg"
    bin_pic = binarization_file(pic,black_font=True)
    time_text = ocr(bin_pic)
    timestamp = time2timestamp(time_text)
    print(timestamp)

本文主要記錄了筆者的一些踩坑經歷,正文部分附的鏈接在解決該問題上都給予了極大的幫助,建議閱讀本文時仔細閱讀參考,也歡迎與筆者交流!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM