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

Numpy 为什么cv2.calcOpticalFlowFarneback在简单的合成示例中失败?,numpy,opencv,image-processing,computer-vision,opticalflow,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,

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)
等于

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
作为第三个参数,我相信)

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

尝试添加一些噪声,例如
a[4,4]+=1在调用roll之前,您将看到一个很大的差异

编辑:添加我的结果

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
原因是等式19、20、23和25中的[1]

值得注意的是,(很抱歉,没有
mathJax
抱怨,很难写出方程)

在您的示例中,这将减少到
np.zero((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
核心代码),但基于的
mineigsthreshold
参数的文档,似乎跳过了奇异矩阵。这可能意味着您的输出是缓冲区垃圾,或者至少是缓冲区垃圾的高斯混合

这也是@JulioDanielReyes在添加噪声参数时能够得到响应的原因-这添加的
I_x
项刚好足以使
G
非单数

参考:

[1] Lucas Kanade特征跟踪器的金字塔实现
算法说明,Jean-Yves Bouguet

是否适用于大小为
(10,10)
的“图像”?而且,当运动是纯仿射的时候,你的算法背后的算法似乎真的不喜欢——这使得最小二乘算法背后的矩阵不可逆。参见第4页底部@DanielF不确定哪个winsize是合适的,但是
flow
基本上仍然是0,其他
winsize
值(例如2或5)在第一个等式中缺少参数?