【问题标题】:Detect bad frames in OpenCV 2.4.9在 OpenCV 2.4.9 中检测坏帧
【发布时间】:2014-06-30 11:39:47
【问题描述】:

我知道标题有点含糊,但我不确定如何描述它。

带有 ffmpeg + OpenCV 2.4.9 的 CentOS。我正在开发一个简单的运动检测系统,它使用来自 IP 摄像机(h264)的流。

流偶尔会打嗝并抛出“坏帧”(请参阅​​下面的 pic-bad.png 链接)。问题是,这些帧与之前的帧有很大不同,即使没有发生实际运动,也会触发“运动”事件。

下面的图片将解释问题。

好帧(运动捕捉):

坏帧(没有运动,只是一个破碎的帧):

坏帧被随机捕获。我想我可以通过分析(循环)从某个位置向下的像素来制作一个坏帧检测器,看看它们是否都相同,但我想知道是否还有其他更有效的方法,“按书" 检测这些类型的坏帧并跳过它们的方法。

谢谢!

编辑更新:

帧是通过cvQueryFrame(camera); 使用 C++ 运动检测程序抓取的,所以我不直接与 ffmpeg 交互,OpenCV 在后端进行。我正在使用从 git 源编译的最新版本的 ffmpeg。所有的库也是最新的(h264 等,昨天全部下载并编译)。数据来自 RTSP 流 (ffserver)。我已经测试了多台相机(大华 1 - 3 MP 型号),并且帧故障在所有相机上都非常持久,尽管它不会连续发生,只是偶尔发生一次(例如:每 10 分钟一次)。

【问题讨论】:

  • 你是如何抓帧的?
  • 可能是ffmpeg编解码器。但是您可以在录制的视频上对其进行测试。 See this
  • 帧是通过cvQueryFrame(camera); 使用C++ 运动检测程序抓取的,所以我不直接与ffmpeg 交互,OpenCV 在后端进行。我正在使用从 git 源编译的最新版本的 ffmpeg。所有的库也是最新的。数据来自 RTSP 流。我已经在多台相机(大华)上进行了测试,并且帧故障非常持久,尽管它不会连续发生,只是偶尔发生一次(例如:每 10 分钟一次)。
  • cvQueryFrame(camera); 我认为是C版本,但你能发布一些代码吗?也许你应该在 for 循环的末尾放一个cv::waitKey(10);,它可能太快了(也许......)
  • 我确实有等待代码,waitKey(50)。我之前已经看过很多次了,但是在观看 @ ~30fps 的视频时,每秒看到的 30 帧中的单帧并不是什么大问题,但是,在进行帧分析时却是。我有点惊讶没有人在 ffmpeg 上看到过这样的行为。我 99% 确定这是由 ffmpeg 端的一些解码问题引起的,我只是好奇是否有任何方法可以防止它或自动检测并丢弃。

标签: c++ opencv ffmpeg motion


【解决方案1】:

我想到的第一种方法是通过计算不同的像素来检查有效帧示例与我们正在检查的帧之间的差异。将此数字除以面积,我们得到衡量差异的百分比。我猜在 0.5 以上,我们可以说测试帧无效,因为它与有效帧的示例差异太大。

仅当您有一个静态相机(它不移动)并且可以在它前面移动的物体不是在最短距离内(取决于焦距,但如果您有例如广角镜头)时,此假设才适用物体不应出现在镜头前 30 厘米以内,以防止物体从无处“跳”入画面,并使其尺寸大于画面面积的 50%)。

这里有 opencv 函数,可以按照我说的做。事实上,如果您认为运动变化会更快,您可以将相异系数调整得更大。请注意,第一个参数应该是有效帧的示例。

bool IsBadFrame(const cv::Mat &goodFrame, const cv::Mat &nextFrame) {
    // assert(goodFrame.size() == nextFrame.size())

    cv::Mat g, g2;
    cv::cvtColor(goodFrame, g, CV_BGR2GRAY);
    cv::cvtColor(nextFrame, g2, CV_BGR2GRAY);

    cv::Mat diff = g2 != g;

    float similarity = (float)cv::countNonZero(diff) / (goodFrame.size().height * goodFrame.size().width);

    return similarity > 0.5f;
}

【讨论】:

  • 这种方法可能行得通,我还没有测试过(我没有在机器前用代码)但这里有一个问题...... C++ 应用程序的目的 + OpenCV在这种情况下是检测运动。通过比较当前帧与前一帧的变化(已经)来检测运动,这就是为什么我们在当前没有任何变化时看到“运动”......现在,如果一辆车停在相机前面,它会导致像素/颜色/等的巨大变化,但我认为它也会触发上面的“IsBadFrame”功能。
【解决方案2】:

你没有提到你是否使用 ffmpeg 命令行或库,但在后一种情况下,你可以检查坏帧标志(我忘记了它的确切描述)并忽略那些帧。

【讨论】:

  • 在后期编辑中添加。它是通过 C++ 和 OpenCV,而不是直接通过 ffmpeg。
【解决方案3】:

删除waitKey(50) 或将其更改为waitKey(1)。我认为 opencv 不会产生一个新线程来执行捕获。所以当有暂停时,它会混淆缓冲区管理例程,导致坏帧..也许?

我有大华相机,观察到延迟越高,就会观察到坏帧。他们完全消失了waitKey(1)。暂停不一定需要来自waitKey。如果调用的时间足够长,调用例程也会导致此类暂停并导致坏帧。

这意味着在连续的帧抓取之间应该有最小的暂停。解决方案是使用两个线程分别执行捕获和处理。

【讨论】:

  • 啊,很有趣。我明天要试试这个。感谢分享!将使用结果更新线程。
  • @user3630380:减少等待是否有效?另外你得到了什么解决方案?谢谢。
猜你喜欢
  • 2014-06-20
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 2015-01-02
  • 1970-01-01
  • 2013-03-07
相关资源
最近更新 更多