繁体   English   中英

Python CV2 从视频中读取过时帧 stream

[英]Python CV2 reads out-of-date frames from video stream

我正在使用 Python 3.9 和 Open-CV (cv2) 从视频 stream 中读取帧并将它们保存为 JPG。

我的程序似乎运行正常。 它捕获视频 stream fine,获取帧,并将它们保存为 JPG。

但是,它从 stream 获取的帧已过时 - 有时会过时几分钟。 视频 stream 中的时钟运行准确,但 JPG 中的时钟显示完全相同(与秒相同 - 但比程序“print()”output 中的日期时间早一分钟或多分钟(以及保存的 JPG 文件时间), 并且在保存时可见的移动对象完全丢失。

奇怪的是:

  1. JPG 图像的大小不相同。 随着序列的进行,它们会增长 10K - 20K。 尽管它们看起来与眼睛相同,但与使用 CV2 进行比较时它们显示出显着差异 - 但如果与使用 PIL 进行比较则没有差异(图像比较要慢大约 10 - 15 倍)。
  2. 摄像头可以配置为在检测到运动时通过 email 发送快照。 这些快照最新的,并显示了当时在画面中的移动物体(但没有时钟显示)。 启用或禁用此功能对从视频 stream 中提取的 JPG 过时的问题没有影响。而且,遗憾的是,快照只有 60K 左右,对于我们的目的来说分辨率太低(这是一个 AI 应用程序需要图片为 600K 或更多)。

相机本身是 ONVIF - 像 PTZ 这样的东西从 Python 代码可以很好地工作。 Synology Surveillance Station 在各个方面都与它配合得很好。 这个 model 具有相当好的规格 - 缩放和良好的 LPR 防眩光功能。 它是中国制造的——但我不想成为“责备工具的穷工”。

任何人都可以在程序代码中发现可能导致此问题的内容吗?

有没有人遇到过这个问题,并且可以建议解决方法或不同的库/方法?

(如果确实是这个品牌 / model 相机的问题,欢迎您插入适合您在此类应用中使用的中档 LPR 相机的插头。)

这是当前的程序代码:

import datetime
from time import sleep

import cv2

goCapturedStream = None
# gcCameraLogin, gcCameraURL, & gcPhotoFolder are defined in the program, but omitted for simplicity / obfuscation.

def CaptureVideoStream():
    global goCapturedStream
    print(f"CaptureVideoStream({datetime.datetime.now()}):  Capturing video stream...")
    goCapturedStream = cv2.VideoCapture(f"rtsp://{gcCameraLogin}@{gcCameraURL}:554/stream0")
    if not goCapturedStream.isOpened():  print(f"Error:  Video Capture Stream was not opened.")
    return

def TakePhotoFromVideoStream(pcPhotoName):
    llResult = False ;  laFrame = None
    llResult, laFrame = goCapturedStream.read()
    print(f"TakePhotoFromVideoStream({datetime.datetime.now()}):  Result is {llResult},  Frame data type is {type(laFrame)}, Frame length is {len(laFrame)}")
    if not ".jpg" in pcPhotoName.lower():  pcPhotoName += ".jpg"
    lcFullPathName = f"{gcPhotoFolder}/{pcPhotoName}"
    cv2.imwrite(lcFullPathName, laFrame)

def ReleaseVideoStream():
    global goCapturedStream
    goCapturedStream.release()
    goCapturedStream = None

# Main Program:  Obtain sequence of JPG images from captured video stream
CaptureVideoStream()
for N in range(1,7):
    TakePhotoFromVideoStream(f"Test{N}.jpg")
    sleep(2)             # 2 seconds
ReleaseVideoStream()

Dan Masek 的建议非常有价值。

当由相机的内置运动检测(在单独的线程中运行并通过全局变量进行通信)触发时,该程序(现在已得到显着增强)可以正确保存最新图像。

关键技巧是:

  1. 一个更快的循环读取帧(并丢弃其中的大部分)。 我将睡眠减少到 0.1(甚至进一步减少到 0.01),并且仅在需要时将相对较少的帧保存为 JPG 文件
  2. 降低相机的帧速率(从 25 到 10 fps - 甚至一次尝试 5 个)。 这意味着相机不会领先于软件并发送不可预测的帧。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM