我正在使用 OpenCV 来计算两个图像之间的光流。我之前是用
cv2.optflow.createOptFlow_DualTVL1()
来计算的。现在我正在尝试使用 cuda 复制结果。我在 CUDA 上尝试了几种光流算法,它们都给出了截然不同的结果。有些甚至按数量级计算。
我用错了吗?或者如果是这样的(我强烈怀疑),哪两种算法(CPU,GPU)将始终给出相同的结果?
下面的一些代码:
optical_flow = cv2.optflow.createOptFlow_DualTVL1()
optical_flow_gpu_0 = cv2.cuda.FarnebackOpticalFlow_create()
H,W = prev.shape[:2]
params = {'perfPreset':cv2.cuda.NvidiaOpticalFlow_2_0_NV_OF_PERF_LEVEL_SLOW,
'outputGridSize':cv2.cuda.NvidiaOpticalFlow_2_0_NV_OF_OUTPUT_VECTOR_GRID_SIZE_1} # Changing this param produces different results but they are still too large flow-vectors.
optical_flow_gpu_1 = cv2.cuda.NvidiaOpticalFlow_2_0_create((W,H),**params)
prev = imgs_gray_batch[0]
curr = imgs_gray_batch[1]
prev_gpu = cv2.cuda_GpuMat(prev)
curr_gpu = cv2.cuda_GpuMat(curr)
flow_cpu = optical_flow.calc(prev,curr,None)
flow_gpu_cuda = optical_flow_gpu_0.calc(prev_gpu, curr_gpu, None)
flow_gpu0 = flow_gpu_cuda.download().astype(np.float32)
flow_gpu_cuda = optical_flow_gpu_1.calc(prev_gpu, curr_gpu, None)
flow_gpu1 = flow_gpu_cuda[0].download().astype(np.float32)
def max_rho(flow):
#flow = flow.download().astype(np.float32)
fx,fy = np.split(flow,2,axis=2)
f_rho = np.sqrt(fx*fx + fy*fy)
max_rho = f_rho.max()
print(max_rho)
max_rho(flow_cpu)
max_rho(flow_gpu0)
max_rho(flow_gpu1)
-------------------------------
# The max value of flows are of different magnitude...
2.4124358
3.2447324
64.0
还有一些图片
plt.figure(figsize = (20,20))
plt.subplot(1,6,1)
plt.imshow(flow_cpu[:,:,0], cmap = 'hot', interpolation = 'nearest')
plt.colorbar()
plt.subplot(1,6,2)
plt.imshow(flow_cpu[:,:,1], cmap = 'hot', interpolation = 'nearest')
plt.colorbar()
plt.subplot(1,6,3)
plt.imshow(flow_gpu0[:,:,0], cmap = 'hot', interpolation = 'nearest')
plt.colorbar()
plt.subplot(1,6,4)
plt.imshow(flow_gpu0[:,:,1], cmap = 'hot', interpolation = 'nearest')
plt.colorbar()
plt.subplot(1,6,5)
plt.imshow(flow_gpu1[:,:,0], cmap = 'hot', interpolation = 'nearest')
plt.colorbar()
plt.subplot(1,6,6)
plt.imshow(flow_gpu1[:,:,1], cmap = 'hot', interpolation = 'nearest')
plt.colorbar()
print('Max')
OpenCV 的这一部分的文档非常少,所以不知道该怎么做。
您使用的光流算法不同,opencv中的某些光流算法确实从相同的输入数据返回不同的结果。我认为这可能是CPU和GPU给出不同结果的问题。如果你想检查cpu和gpu结果,你至少应该使用相同的输入数据和相同类型的算法(如cpu和gpu版本的Farneback算法)。
您可能正在寻找
convertToFloat()
功能。像这样使用:
sz = 1024
nvof = cv.cuda_NvidiaOpticalFlow_2_0.create((sz,sz), outputGridSize = 4, perfPreset = 5)
im1 = cv.cuda_GpuMat(np.random.rand(sz,sz))
im2 = cv.cuda_GpuMat(np.random.rand(sz,sz))
output = nvof.calc(im1, im2, None, None)
output_cpu = cv.cuda_GpuMat.download(nvof.convertToFloat(output[0], None))