C++ 在OpenCV 2.4.9中检测坏帧

C++ 在OpenCV 2.4.9中检测坏帧,c++,opencv,ffmpeg,motion,C++,Opencv,Ffmpeg,Motion,我知道这个标题有点模糊,但我不知道该如何描述它 CentOS采用ffmpeg+OpenCV 2.4.9。我正在开发一个简单的运动检测系统,它使用来自IP摄像机(h264)的流 偶尔,流会打嗝并抛出一个“坏帧”(参见下面的pic-bad.png链接)。问题是,这些帧与以前的帧差别很大,即使没有实际运动发生,也会触发“运动”事件 下面的图片将解释问题 好帧(捕捉到的运动): 坏帧(没有运动,只是坏帧): 坏帧被随机捕获。我想我可以通过分析(循环)从某个位置向下的像素来制作一个坏帧检测器,看看它们

我知道这个标题有点模糊,但我不知道该如何描述它

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

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

下面的图片将解释问题

好帧(捕捉到的运动):

坏帧(没有运动,只是坏帧):

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

谢谢大家!

编辑更新:


使用C++的运动检测程序,通过<代码> CVQuyReFrice(相机),获取帧;代码>所以我不直接与ffmpeg接口,OpenCV在后端完成。我使用的是从git源代码编译的最新版本的ffmpeg。所有的库都是最新的(h264等,都是昨天下载和编译的)。数据来自RTSP流(ffserver)。我已经测试了多个摄像头(dahua 1-3 MP型号),所有摄像头的帧故障都相当持久,尽管它不是连续发生的,只是偶尔发生一次(例如:每10分钟一次)

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

此假设仅适用于静态摄像机(不移动),且可在其前面移动的物体不在最短距离内(取决于焦距,但如果您有宽镜头,则物体在摄像机前面的距离不应小于30 cm,以防止物体“跳跃”的情况从任何地方进入一个框架,并且其大小大于框架面积的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;
}

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

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

我有大华相机,观察到延迟越大,观察到的帧越差。它们会随着
waitKey(1)
完全消失。暂停不一定来自
waitKey
。调用例程也会导致此类暂停,如果它们花费的时间足够长,则会导致坏帧


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

如何抓取帧?可能是ffmpeg编解码器。但是你可以在录制的视频上测试它。利用C++的运动检测程序,通过<代码> CVQuyReFrice(相机),抓取框架;代码>所以我不直接与ffmpeg接口,OpenCV在后端完成。我使用的是从git源代码编译的最新版本的ffmpeg。所有的图书馆都是最新的。数据来自RTSP流。我在多个摄像头(dahuas)上进行了测试,虽然帧故障不会持续发生,只是偶尔发生一次(例如:每10分钟一次)。
cvQueryFrame(摄像头)我认为是C版本,但是你能发布一些代码吗?也许你应该放一个
cv::waitKey(10)在for循环的末尾,它可能太快了(可能…)我确实有等待代码,
waitKey(50)
。我以前见过很多这样的画面,但是当我观看一段每秒30帧的视频时,每秒30帧中的一帧并不是什么大不了的事情,然而,当我们进行帧分析时,这是一件大不了的事情。我有点惊讶,没有人在ffmpeg中看到这样的行为。我99%确定这是由ffmpeg方面的解码问题引起的,我只是好奇是否有任何方法可以防止它或自动检测和删除。这种方法可能有效,我还没有测试过它(我没有在机器前面的代码),但这里有一个问题。。。在这种情况下,C++ APP+OpenCV的目的是检测运动。通过比较当前帧和前一帧的变化(已经)来检测运动,这就是为什么我们在当前没有任何变化的情况下看到“运动”。。。现在,如果一辆车停在摄像机前面,它将导致像素/颜色/等的巨大变化,但我认为它也会触发上面的“IsBadFrame”功能。在后期编辑中添加。它是通过C++和OpenCV,而不是直接通过FFMPEG。啊,非常有趣。我明天要试试这个。谢谢分享!将使用结果更新线程。@user3630380:减少等待是否有效?你也得出了什么解决方案?非常感谢。