TVL1算法:
https://blog.csdn.net/weixin_41558411/article/details/89855290
核心函数:
TVL1 = cv2.DualTVL1OpticalFlow_create()
flow = TVL1.calc(prev, curr, None)
速度较慢,两张之间的光流图计算耗时大概6-11s左右
Farneback算法
https://github.com/jiangzhubo/extract_optical_flow/blob/master/extractallopt.py
核心函数:
cv2.calcOpticalFlowFarneback(prev, curr, None, 0.5, 3, 15, 3, 5, 1.2, 0)
速度较快,两张之间的光流图计算耗时大概0.1s左右
上面两种方法均只使用CPU运算,未使用GPU加速!所以第一种算法较慢,照理来说可以编译gpu版opencv,不过编译opencv实在是各种报错。不过TVL1算法得到的光流图片与论文中的更加相似,均为灰色的,Farneback就不太像。
通常网络所需要的光流输入如i3d的光流输入的通道数为二通道,而一般网上所使用Farneback算法提取光流后并保存光流的方法如下(先使用Farneback算法提取二通道的光流,然后转换为hsv格式,最后转为bgr格式使用cv2保存下来;但这个过程由于np.minimum是一个不可逆的过程,即保存后的光流bgr图片后续不能转换为我网络所需要的二通道数组;还有由于通过Farneback提取的二通道光流数组为浮点型且还存在负数,这使得无法把二通道的数组直接多加一个通道变为数据类型为uint8的图片数组,浮点型数据将会取整,且负数均为0;再一个直接使用npy保存二通道光流数组,由于视频数据较多,占用空间可能是图片的几百倍;所以最后二通道的光流数组还是边训练的时候边提取,虽然这样训练会慢不少,我这是慢了5倍)
def draw_hsv(flow):
h, w = flow.shape[:2]
fx, fy = flow[:,:,0], flow[:,:,1]
ang = np.arctan2(fy, fx) + np.pi
v = np.sqrt(fx*fx+fy*fy)
hsv = np.zeros((h, w, 3), np.uint8)
hsv[...,0] = ang*(180/np.pi/2)
hsv[...,1] = 255
hsv[...,2] = np.minimum(v*4, 255)
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
return bgr
case_dir = ...
files = os.listdir(case_dir)
files.sort()
prev = cv2.cvtColor(cv2.imread(case_dir + files[0]), cv2.COLOR_BGR2GRAY)
for file in files:
t1 = time.time()
file_dir = case_dir + file
curr = cv2.cvtColor(cv2.imread(file_dir), cv2.COLOR_BGR2GRAY)
flow = cv2.calcOpticalFlowFarneback(prev, curr, None, 0.5, 3, 15, 3, 5, 1.2, 0)
prev = curr
bgr = draw_hsv(flow)
cv2.imwrite(optical_flow_dir + folder + '/' + disease_type + '/' + patient + '/' + case + '/' + file, bgr,
[cv2.IMWRITE_JPEG_QUALITY, 12])
t2 = time.time()
print(str(t2 - t1), 'seconds')
可能的其他方法(待测):
https://github.com/feichtenhofer/gpu_flow
https://github.com/yjxiong/dense_flow