简体   繁体   English

检测OpenCV 2.4.9中的坏帧

[英]Detect bad frames in OpenCV 2.4.9

I know the title is a bit vague but I'm not sure how else to describe it. 我知道标题有点模糊,但我不确定如何描述它。

CentOS with ffmpeg + OpenCV 2.4.9. CentOS与ffmpeg + OpenCV 2.4.9。 I'm working on a simple motion detection system which uses a stream from an IP camera (h264). 我正在研究一种简单的运动检测系统,它使用来自IP摄像机的流(h264)。

Once in a while the stream hiccups and throws in a "bad frame" (see pic-bad.png link below). 偶尔流会打嗝并抛出一个“坏帧”(见下面的pic-bad.png链接)。 The problem is, these frames vary largely from the previous frames and causes a "motion" event to get triggered even though no actual motion occured. 问题是,这些帧在很大程度上与先前帧不同,并且即使没有发生实际运动也会导致“运动”事件被触发。

The pictures below will explain the problem. 下面的图片将解释这个问题。

Good frame (motion captured): 好帧(捕获的动作):

好框架

Bad frame (no motion, just a broken frame): 坏帧(没有动作,只是一个破帧):

糟糕的框架

The bad frame gets caught randomly. 坏帧被随机捕获。 I guess I can make a bad frame detector by analyzing (looping) through the pixels going down from a certain position to see if they are all the same, but I'm wondering if there is any other, more efficient, "by the book" approach to detecting these types of bad frames and just skipping over them. 我想我可以通过分析(循环)通过从某个位置向下的像素来制作一个糟糕的帧检测器,看看它们是否完全相同,但我想知道是否还有其他的,更有效的,“这本书“检测这些类型的坏帧并跳过它们的方法。

Thank You! 谢谢!

EDIT UPDATE: 编辑更新:

The frame is grabbed using a C++ motion detection program via cvQueryFrame(camera); 通过cvQueryFrame(camera);使用C ++运动检测程序抓取帧cvQueryFrame(camera); so I do not directly interface with ffmpeg, OpenCV does it on the backend. 所以我不直接与ffmpeg接口,OpenCV在后端做它。 I'm using the latest version of ffmpeg compiled from git source. 我正在使用从git源编译的最新版本的ffmpeg。 All of the libraries are also up to date (h264, etc, all downloaded and compiled yesterday). 所有的库都是最新的(h264等,昨天全部下载和编译)。 The data is coming from an RTSP stream (ffserver). 数据来自RTSP流(ffserver)。 I've tested over multiple cameras (dahua 1 - 3 MP models) and the frame glitch is pretty persistent across all of them, although it doesn't happen continuously, just once on a while (ex: once every 10 minutes). 我已经测试了多台摄像机(大华1 - 3 MP机型),并且机架故障在所有这些机架上非常持久,虽然它不会连续发生,只是偶尔发生一次(例如:每10分钟一次)。

What comes to my mind in first approach is to check dissimilarity between example of valid frame and the one we are checking by counting the pixels that are not the same. 在第一种方法中我想到的是通过计算不相同的像素来检查有效帧的示例与我们正在检查的示例之间的不相似性。 Dividing this number by the area we get percentage which measures dissimilarity. 将这个数除以面积,我们得到衡量不相似度的百分比。 I would guess above 0.5 we can say that tested frame is invalid because it differs too much from the example of valid one. 我猜大于0.5我们可以说测试帧是无效的,因为它与有效帧的例子有很大不同。

This assumption is only appropriate if you have a static camera (it does not move) and the objects which can move in front of it are not in the shortest distance (depends from focal length, but if you have eg wide lenses so objects should not appear less than 30 cm in front of camera to prevent situation that objects "jumps" into a frame from nowhere and has it size bigger that 50% of frame area). 这个假设只适用于你有一个静态相机(它不移动),并且可以在它前面移动的物体不在最短距离内(取决于焦距,但如果你有例如宽镜头那么物体不应该在相机前方出现不到30厘米,以防止物体从不知名的地方“跳入”框架并且其尺寸大于框架区域的50%)。

Here you have opencv function which does what I said. 在这里你有opencv功能,它做我说的。 In fact you can adjust dissimilarity coefficient more large if you think motion changes will be more rapid. 实际上,如果您认为运动变化会更快,您可以将相似系数调整得更大。 Please notice that first parameter should be an example of valid frame. 请注意,第一个参数应该是有效帧的示例。

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命令行或库,但在后一种情况下,您可以检查坏帧标志(我忘记了它的确切描述)并简单地忽略这些帧。

remove waitKey(50) or change it to waitKey(1) . 删除waitKey(50)或将其更改为waitKey(1) I think opencv does not spawn a new thread to perform capture. 我认为opencv不会产生一个新线程来执行捕获。 so when there is a pause, it confuses the buffer management routines, causing bad frames..maybe? 所以当有一个暂停时,它会混淆缓冲区管理例程,导致坏帧...可能?

I have dahua cameras and observed that with higher delay, bad frames are observed. 我有大华相机,并观察到延迟较高,观察到坏帧。 And they go away completely with waitKey(1) . 然后他们完全用waitKey(1)离开了。 The pause does not necessarily need to come from waitKey . 暂停不一定需要来自waitKey Calling routines also cause such pauses and result in bad frames if they are taking long enough. 调用例程也会导致这种暂停,并且如果它们花费的时间足够长,则会导致错误的帧。

This means that there should be minimum pause between consecutive frame grabs.the solution would be to use two threads to perform capture and processing separately. 这意味着连续帧抓取之间应该有最小的暂停。解决方案是使用两个线程分别执行捕获和处理。

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

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