带有遮罩的密集光流

时间:2019-07-03 21:35:14

标签: python opencv opticalflow

我需要计算从高架摄像机记录的两个连续帧之间车辆的密集光流。我正在使用对象检测器进行车辆检测,并使用Farneback算法进行Python中的光流估计。当前,为整个图像计算光流。但是,我需要在检测到的车辆周围创建一个遮罩,并仅在所选区域周围计算密集的光流。这将有助于显着加快光流估计。我也可以使用任何其他形式的密集光流估计,但不能使用稀疏光流(例如,Lucas-Kanade方法)。一种选择是提取车辆区域并分别输入每个车辆区域以进行光流估计,但我正在寻找更好的解决方案。

flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)

在没有任何光流计算的情况下,非车辆遮挡区域的预期光流结果将为零。

2 个答案:

答案 0 :(得分:1)

不幸的是,通过掩盖或仅提供检测器的边界框来按计划加速运动估计将不是一个好主意。如果使用密集的光流方法,则需要提供整个图像并计算整个图像的流场。 如果通过去除覆盖图像,则会引入人为边缘,这会混淆该方法。 另一方面,单独输入每个车辆区域,您将失去密集流动方法计算较大(快速)运动的能力。 Farneback之类的方法使用图像金字塔来处理较大的运动,即它们基于缩小输入图像的比例。如果区域小于此范围,则将无法计算大型运动。 减少运行时间的一种可能性是将稀疏方法(例如Lucas Kanade或RLOF)应用到您的车辆区域,并将SparseToDense插值(例如OpenCV中的EdgeAwareInterpolation)应用于您的车辆区域,并获取该区域的密集运动场。

答案 1 :(得分:0)

对于某些光流使用案例,这可能是一种健康的加速方法。

为确保我们在同一页面上,光流不会直接用作跟踪汽车的主要信息来源。这是由另一个模块处理的……可能是一些基于深度学习的对象检测器。该对象检测器可能需要进行大量计算(除非您为此配备了一些特殊的硬件,例如专用GPU或VPU)。

密集的流动可能是一个很好的称赞,它可以获取有关汽车及其周围发生的事件的低延迟信息,并且可以用作引导后面的检测器的一部分(在后续检测器中先于检测器帧,如Kalman过滤器跟踪设置中的设置。

有了这个假设,您就可以轻松地优化您提到的光流计算。我建议您在这里跳过密集遮罩的概念,只需使用检测器中的边界框即可。这将是您感兴趣的流量计算区域。如果您位于第t帧中检测所在的位置,并且想要使用2帧t和t-1中的光流,则对这两个帧使用相同的边界框。这将为您提供2个ROI,并将这些ROI馈送到您的密集光流模块中。

每个光流算法都有用于其低级操作的支持区域,它们不能很好地处理图像边界。因此,请确保为边界框提供足够的额外空间(只要它们能适合原始视频帧)。

为清楚起见,如果您将用于汽车检测的边界框设为bbox(x,y,w,h),则需要一个足够的裕度m,以便用于密集流动的边界框为bbox(xm / 2,ym / 2,w + m,h + m)。边距是您要根据光流方法(及其参数)设置的。

编辑:在这里为您编写代码,随您去。注意,我根本没有测试过:

// This is c++, since we are talking optimizations
// I am uncertain of they python wrappers, but below I am fairly certain
// will not make any deep copies outside of the flow module.
// Assume you have INew and IOld, the two frames of the video:
// assume your bounding box from your detector is a cv::Rect b
float m = 4.0; // 4 pixels as an example margin...
Rect boxFlow(b.x - m/2, b.y - m/2, b.width + m, b.height + m);
Mat roiNew(INew (boxFlow));
Mat roiOld(IOld (boxFlow));
Mat uflow;
calcOpticalFlowFarneback(roiOld, roiNew, uflow, 0.5, 3, 15, 3, 5, 1.2, 0);

但是,最终取决于您的设置,这可能不会显着提高速度。对于以上代码,我不知道流模块内部如何处理内存,而在您的python版本中,我什至不确定如何处理内存。

请考虑在简化的密集光流方法(使用相同大小的数据输出)中,您在管道中具有相同大小的内存缓冲区。您提到的方法的幼稚实现将需要动态分配内存,因为边界框的大小和数量会随时间变化。