【附代码实现】光流法大全(DeepFlow、DenseFlow、DisFlow、FbFlow、PCAFlow、SimpleFlow、TV_L1)

前言

我研究生阶段是做深度学习情感识别的,在研究阶段曾经尝试过使用光流法来捕捉情感的变化,也花费了大量的时间去尝试各种光流法,走了不少弯路。现在研究生毕业了,就总结以下之前研究中所使用到的光流法。光流法分为传统的光流法和使用深度学习技术的光流法,这次分享仅仅涉及传统的光流法。

光流法是一种有效的提取人脸表情特征的方法,人脸表情的变化会引起相应位置像素点亮度的变化,光流法的实质就是对像素点的追踪:在相邻的图像帧之间,在下一个时刻的图像中寻找上一个时刻图像的关键的位置。

原始图像
在这里插入图片描述

一、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)
  • 20
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值