为什么cv2.calcOpticalFlowFarneback在简单的合成示例上失败?

时间:2017-10-02 08:22:03

标签: numpy opencv image-processing computer-vision opticalflow

cv2.calcOpticalFlowFarneback似乎在自然图像上运行良好,但是如果我在简单的合成示例上尝试它,例如下面的那个,它认为没有流程:

import cv2
import numpy as np

a = np.zeros((10, 10), dtype=np.uint8); a[1:4] = 127; a[2] = 255; a

等于

array([[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [127, 127, 127, 127, 127, 127, 127, 127, 127, 127],
       [255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
       [127, 127, 127, 127, 127, 127, 127, 127, 127, 127],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

b = np.roll(a, 1, 0); b

等于

array([[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [127, 127, 127, 127, 127, 127, 127, 127, 127, 127],
       [255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
       [127, 127, 127, 127, 127, 127, 127, 127, 127, 127],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

流程:

flow = cv2.calcOpticalFlowFarneback(a, b, pyr_scale=0.5, levels=3, winsize=15, iterations=3, poly_n=5, poly_sigma=1.2, flags=0)

基本上为0,如

np.abs(flow).max()

评估为

1.3305091e-13

我尝试了不同的winsize值,结果相似。

为什么会这样?还有其他参数可以更好地运作吗?

(我的OpenCV版本是2.4.8。版本3需要添加None作为第三个参数,我相信)

2 个答案:

答案 0 :(得分:2)

原因是方程19,20,23和25中的here [1]。

值得注意的是(抱歉,很难在没有mathJax 抱怨的情况下编写公式

I_x[x,y] = (A[x-1, y] - A[x+1, y]) / 2  # Equation 19

这会缩小为示例中的np.zeros((10,10)),从而导致后续问题:

G = sum([[I_x**2, I_x * I_y],[I_x * I_y, I_y**2]], axis = (2,3))  # Equation 23

由于I_x为零,这意味着G采用

形式
G = [[0, 0], [0, I_y**2]]

无处不在,这是一个奇异的矩阵。由于需要反转,解算器会卡住。

之后发生的事情很难理解(我不能很好地阅读c以深入研究openCV核心代码),但似乎基于文档的文档会跳过单个矩阵。 calcOpticalFlowPyrLKminEigThreshold参数。这可能意味着您的输出是缓冲垃圾,或者至少是缓冲垃圾的高斯混合。

这也是为什么@JulioDanielReyes在添加噪声参数时能够得到响应的原因 - 这会增加足够的I_x个术语以使G成为非单数。

价:

[1] Lucas Kanade特征追踪器的金字塔形实现 该算法的描述,Jean-Yves Bouguet

答案 1 :(得分:1)

我不知道这是否会回答你的问题,但除了winsize太大之外,算法很难知道哪个方向正在移动(左/右)这样的常规数字。

尝试添加一些噪音,例如在致电滚动之前a[4,4] += 1;,你会看到很大的不同。

修改:添加了我的搜索结果

print(np.abs(flow).max())

没有噪音:

winsize 15: 1.33051e-13
winsize 2: 6.00387e-11

噪音1:

# a[4,4] += 1; 
winsize 15: 0.00332422
winsize 2: 1.82871

噪音2:

# noise = np.round(np.random.random(a.shape) * 2.0).astype(np.int8)
# a = a + noise;
winsize 15: 0.207728
winsize 2: 324.527