获取监控视频图像帧的时间戳


背景:

我们采集了一系列的监控视频,视频的左上角会实时显示时间。通过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