文章目录
- 前言
- 一、DIS光流法
- 1.1 理论
- 1.2 效果图
- 1.3 程序
- 二、DeepFlow光流法
- 2.1 效果图
- 2.2 程序
- 三、DeepFlow光流法
- 3.1 效果图
- 3.2 程序
- 四、FB光流法
- 4.1 效果图
- 4.2 程序
- 五、PCA光流法
- 5.1 效果图
- 5.2 程序
- 六、PCA光流法
- 6.1效果图
- 6.2 程序
- 七、TV_L1光流法
- 7.1 效果图
- 7.2 程序
前言
我研究生阶段是做深度学习情感识别的,在研究阶段曾经尝试过使用光流法来捕捉情感的变化,也花费了大量的时间去尝试各种光流法,走了不少弯路。现在研究生毕业了,就总结以下之前研究中所使用到的光流法。光流法分为传统的光流法和使用深度学习技术的光流法,这次分享仅仅涉及传统的光流法。
光流法是一种有效的提取人脸表情特征的方法,人脸表情的变化会引起相应位置像素点亮度的变化,光流法的实质就是对像素点的追踪:在相邻的图像帧之间,在下一个时刻的图像中寻找上一个时刻图像的关键的位置。
原始图像
一、DIS光流法
1.1 理论
DIS光流算法是基于前后两帧图像中所有像素点的移动估算算法,通过每个像素点的邻域信息来对该像素点的坐标位置进行多项式展开得到一个以原坐标(x0,y0)为自变量,新坐标(x,y)为因变量的多项式,并代入坐标数据来求取该像素点在x和y方向上的移动量(dx,dy)。这样就得到了每个像素点在前后两帧图像中的位移矢量,包含振幅和相位。
算法:使用Till Kroeger提出的DIS光流法[1]计算全局性的稠密光流,将图像上所有的像素点的光流都计算出来
[1]Kroeger,T&R.Timofte&D.X.Dai&L.V. Gool. Fast Optical Flow Using Dense Inverse Search [J] .2016-09-17
1.2 效果图
DIS光流法后
1.3 程序
import os
import cv2
import numpy as np
import flow_vis
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list=os.listdir(src)
file_list = sorted(file_list)
# print(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[...,1] = 255
dis = cv2.optflow.createOptFlow_DIS(2)
dis.setUseSpatialPropagation(True)
for file in file_list:
# for i in range(1440):
path = os.path.join(src, file)
frame2 = cv2.imread(path)
next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = dis.calc(prvs, next, None, )
# 笛卡尔坐标转换为极坐标,获得极轴和极角
# mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
# hsv[..., 0] = ang * 180 / np.pi / 2
# hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
# rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
prvs = next
print('img number:%d' % len(os.listdir(des)))
original_dir_path = 'D:\Software\pycharm\DATA_img_2\Train/03017_1'
flow_dir_path = 'D:\Software\pycharm\DATA_img_2\Flow\DIS_flow'
generate_flow(original_dir_path, flow_dir_path)
二、DeepFlow光流法
2.1 效果图
2.2 程序
import os
import cv2
import numpy as np
import flow_vis
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list=os.listdir(src)
file_list = sorted(file_list)
# print(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[...,1] = 255
dis = cv2.optflow.createOptFlow_DeepFlow()
for file in file_list:
# for i in range(1440):
path = os.path.join(src, file)
frame2 = cv2.imread(path)
next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = dis.calc(prvs, next, None)
# flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 25, 3, 5, 1.2, 1)
# # print(flow.shape)
# print(flow)
# # 笛卡尔坐标转换为极坐标,获得极轴和极角
# mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
# hsv[..., 0] = ang * 180 / np.pi / 2
# hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
# rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
prvs = next
print('img number:%d' % len(os.listdir(des)))
original_dir_path = 'D:\Software\pycharm\DATA_img_2\Train/03017_1'
flow_dir_path = 'D:\Software\pycharm\DATA_img_2\Flow\DEEP_flow_1'
generate_flow(original_dir_path, flow_dir_path)
三、DeepFlow光流法
3.1 效果图
3.2 程序
import os
import cv2
import numpy as np
import flow_vis
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list=os.listdir(src)
file_list = sorted(file_list)
# print(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[...,1] = 255
for file in file_list:
# for i in range(1440):
path = os.path.join(src, file)
frame2 = cv2.imread(path)
next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = cv2.optflow.calcOpticalFlowSparseToDense(prvs, next)
rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
prvs = next
print('img number:%d' % len(os.listdir(des)))
original_dir_path = 'D:\Software\pycharm\DATA_img\crop/03022_0'.strip('\u202a')
flow_dir_path = ''
generate_flow(original_dir_path, flow_dir_path)
四、FB光流法
4.1 效果图
4.2 程序
import os
import cv2
import numpy as np
def compute_FlowFarneback(prvs, next):
"""Compute the TV-L1 optical flow."""
flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
return flow
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list = os.listdir(src)
file_list = sorted(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[..., 1] = 255
for file in file_list[0:8]:
prvs_path = os.path.join(src, file_list[0])
prvs = cv2.imread(prvs_path)
prvs = cv2.cvtColor(prvs, cv2.COLOR_BGR2GRAY)
next_path = os.path.join(src, file)
next = cv2.imread(next_path)
next = cv2.cvtColor(next, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = compute_FlowFarneback(prvs, next)
# rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
# 笛卡尔坐标转换为极坐标,获得极轴和极角
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
for count in range(1432):
prvs_path = os.path.join(src, file_list[count])
prvs = cv2.imread(prvs_path)
prvs = cv2.cvtColor(prvs, cv2.COLOR_BGR2GRAY)
next_path = os.path.join(src, file_list[count + 8])
next = cv2.imread(next_path)
next = cv2.cvtColor(next, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = compute_FlowFarneback(prvs, next)
# rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
# 笛卡尔坐标转换为极坐标,获得极轴和极角
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file_list[count + 8]), rgb)
except Exception as e:
continue
print('img number:%d' % len(os.listdir(des)))
if __name__ == '__main__':
original_dir_path = 'D:\Software\pycharm\DATA_img\original/train/03009_1'
flow_dir_path = 'D:\Software\pycharm\DATA_img/flow\TV_Lceshi/03009_1'
generate_flow(original_dir_path, flow_dir_path)
五、PCA光流法
5.1 效果图
5.2 程序
import os
import cv2
import numpy as np
import flow_vis
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list=os.listdir(src)
file_list = sorted(file_list)
# print(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[...,1] = 255
inst = cv2.optflow.createOptFlow_PCAFlow()
for file in file_list:
# for i in range(1440):
path = os.path.join(src, file)
frame2 = cv2.imread(path)
next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = inst.calc(prvs, next, None)
rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
prvs = next
print('img number:%d' % len(os.listdir(des)))
original_dir_path = 'D:\Software\pycharm\DATA_img\crop/03022_0'.strip('\u202a')
flow_dir_path = 'D:\Software\pycharm\DATA_img\crop_flow\PCA_flow'
generate_flow(original_dir_path, flow_dir_path)
六、PCA光流法
程序好像有点问题
6.1效果图
6.2 程序
import os
import cv2
import numpy as np
import flow_vis
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list=os.listdir(src)
file_list = sorted(file_list)
# print(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[...,1] = 255
for file in file_list:
# for i in range(1440):
path = os.path.join(src, file)
frame2 = cv2.imread(path)
next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = cv2.optflow.calcOpticalFlowSF(prvs, next, 3, 5, 5)
# flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 25, 3, 5, 1.2, 1)
# # print(flow.shape)
# print(flow)
# # 笛卡尔坐标转换为极坐标,获得极轴和极角
# mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
# hsv[..., 0] = ang * 180 / np.pi / 2
# hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
# rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
prvs = next
print('img number:%d' % len(os.listdir(des)))
original_dir_path = 'D:\Software\pycharm\DATA_img_2\Train/03017_1'
flow_dir_path = 'D:\Software\pycharmDATA_img_2\Flow\SIMPLE_flow'
generate_flow(original_dir_path, flow_dir_path)
七、TV_L1光流法
7.1 效果图
7.2 程序
import os
import cv2
import numpy as np
# 指定GPU
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" #按照PCI_BUS_ID顺序从0开始排列GPU设备
os.environ["CUDA_VISIBLE_DEVICES"] = "2" #使用第3块GPU进行训练
def compute_TVL1(prev, curr):
"""Compute the TV-L1 optical flow."""
TVL1 = cv2.optflow.DualTVL1OpticalFlow_create()
flow = TVL1.calc(prev, curr, None)
return flow
def generate_flow(src, des): # 以个体为单位生成光流图
"""
:param src: 原图每个个体的文件夹路径
:param des: 光流图每个个体的文件夹路径
:return:
"""
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
file_list=os.listdir(src)
file_list = sorted(file_list)
# 获取第一帧
frame1 = cv2.imread(os.path.join(src, file_list[0]))
hsv = np.zeros_like(frame1)
# 遍历每一行的第一列
hsv[..., 1] = 255
for file in file_list[0:8]:
prvs_path = os.path.join(src, file_list[0])
prvs = cv2.imread(prvs_path)
prvs = cv2.cvtColor(prvs, cv2.COLOR_BGR2GRAY)
next_path = os.path.join(src, file)
next = cv2.imread(next_path)
next = cv2.cvtColor(next, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = compute_TVL1(prvs, next)
# rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
# 笛卡尔坐标转换为极坐标,获得极轴和极角
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file), rgb)
except Exception as e:
continue
for count in range(1430):
prvs_path = os.path.join(src, file_list[count])
prvs = cv2.imread(prvs_path)
prvs = cv2.cvtColor(prvs, cv2.COLOR_BGR2GRAY)
next_path = os.path.join(src, file_list[count+8])
next = cv2.imread(next_path)
next = cv2.cvtColor(next, cv2.COLOR_BGR2GRAY)
# 返回一个两通道的光流向量,实际上是每个点的像素位移值
flow = compute_TVL1(prvs, next)
# rgb = flow_vis.flow_to_color(flow, convert_to_bgr=False)
# 笛卡尔坐标转换为极坐标,获得极轴和极角
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
mkfile(des)
# 写入新的文件夹
try:
cv2.imwrite(os.path.join(des, file_list[count+8]), rgb)
except Exception as e:
continue
print('img number:%d' % len(os.listdir(des)))
if __name__ == '__main__':
original_dir_path = 'D:\Software\pycharm\DATA_img\original/train/03022_1'
flow_dir_path = 'D:\Software\pycharm\DATA_img/flow\TV_Lceshi/03022_1'
generate_flow(original_dir_path, flow_dir_path)