zoukankan      html  css  js  c++  java
  • 光流算法的理解与实现

        光流估计实际上是根据两张连续的帧,去估计两帧之间 pixel-wise(基于物体像素)的光流。凡是有关估计相关的东西,卷积神经网络经过大量数据学习后都能拟合,只要有足够的训练数据和一个较好的网络结构。FlowNet 开辟了这个工作,同时也发布了一个光流估计的数据集。

        光流追踪法 分为 稀疏光流追踪,与稠密光流追踪。二者的区别就是在于,稀疏光流追踪法,稀疏光流不对图像的每个像素点进行逐点计算,它通常需要指定一组点进行跟踪,这组点需要具有某种明显的图像特征,例如 Harris 角点或者其他特征等,那么跟踪就会相对稳定和可靠。稀疏光流跟踪的计算开销比稠密光流跟踪小得多。这样计算量减少了很多。下面是稀疏光流法的一个python-opencv实现:

    import numpy as np
    import cv2
    
    cap = cv2.VideoCapture('test1.avi')
    
    # 得到视频的高度
    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    # 得到视频的宽度
    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    # 得到视频的帧数
    count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    # 得到视频的帧速
    fps = cap.get(cv2.CAP_PROP_FPS)
    
    # 定义写入视频的编码格式
    fourcc = cv2.VideoWriter_fourcc(*'XVID')  #  *'XVID' or *'MJPG'  写入视频类的编码格式
    # 创建写入视频的类
    temp_video = cv2.VideoWriter("LK_method.avi", fourcc, int(fps), (int(width), int(height)))
    
    # 定义写入视频的编码格式
    fourcc = cv2.VideoWriter_fourcc(*'XVID')  #  *'XVID' or *'MJPG'  写入视频类的编码格式
    # 创建写入视频的类
    output_video = cv2.VideoWriter("LK_method_output.avi", fourcc, int(fps), (int(width), int(height)))
    
    # 定义随机颜色
    color = np.random.randint(0,255,(100,3))
    
    # 读取第一帧
    ret, old_frame = cap.read()
    old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
    # 检测第一帧图像的特征点
    p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, maxCorners=100,qualityLevel=0.01,minDistance=10,blockSize=3)
    
    # 稀疏光流跟踪
    while True:
        ret, frame = cap.read()
        if ret is False:
            break
        frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 计算光流
        p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None,winSize=(31, 31), maxLevel=3, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 30, 0.01))
        # 根据状态选择
        good_new = p1[st == 1]
        good_old = p0[st == 1]
    
        # 绘制跟踪线
        for i, (new, old) in enumerate(zip(good_new,good_old)):
            a,b = new.ravel()
            c,d = old.ravel()
            frame = cv2.line(frame, (a,b),(c,d), color[i].tolist(), 2)
            frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
            temp_video.write(frame)
        cv2.imwrite("LK_output.jpg",frame)
        output_video.write(frame)
        # 更新
        old_gray = frame_gray.copy()
        p0 = good_new.reshape(-1, 1, 2)
    
    cap.release()

    可以看到图中,即是视频的一帧,对人的运动进行了一个跟踪。根据图像会发现稀疏光流法的效果并不是很好。

    下面介绍一下稠密光流法,主要是Farneback 光流算法的实现。

    import cv2
    import numpy as np
    
    # 绘制光流场图像
    def drawOptFlowMap(flow,cflowmap,step,color):
        # 以 step 步长遍历图像
        for x in range(0,flow.shape[1],step):
            for y in range(0,flow.shape[0],step):
                # 绘制跟踪线
                cv2.line(cflowmap, (x,y), (int(x+flow[y][x][0]),int(y+flow[y][x][1])),color)
                cv2.circle(cflowmap,(x, y), 2, color, -1)
        return cflowmap
    cap = cv2.VideoCapture('test.avi')
    # 得到视频的高度
    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    # 得到视频的宽度
    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    # 得到视频的帧数
    count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    # 得到视频的帧速
    fps = cap.get(cv2.CAP_PROP_FPS)
    
    # 定义写入视频的编码格式
    fourcc = cv2.VideoWriter_fourcc(*'XVID')  #  *'XVID' or *'MJPG'  写入视频类的编码格式
    # 创建写入视频的类
    output_video = cv2.VideoWriter("GF_method_output.avi", fourcc, int(fps), (int(width), int(height)))
    
    # 读取第一帧图像
    ret, frame1 = cap.read()
    prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)
    
    while(1):
        ret, frame2 = cap.read()
        if ret is False:
            break
        next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)
        # 使用稠密光流算法计算光流
        flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
        # 通过得到的光流绘制图像
        bgr = drawOptFlowMap(flow,frame2,16,(0,255,0))
        cv2.imwrite("GF_output.jpg",bgr)
        output_video.write(bgr)
        # 更新
        prvs = next
    cap.release()

    下面是实现稠密光流法的结果。

    可以看出 稠密光流法,此图片上有采取步长为 16 所绘制的光流场。因此,稠密光流是采取的全部的像素点进行求解,并没有求取图像特征点的步骤。而且上图中有人的区域都存在部分追踪线,可以看出,稠密光流比稀疏光流更为稳定。

    但是稠密光流法的计算量更大,所以速度也会降低很多。

  • 相关阅读:
    RabbitMQ~广播消息
    大数据~说说Hadoop
    大数据~说说ZooKeeper
    RabbitMQ~消费者实时与消息服务器保持通话
    c/c++测试程序运行时间
    7kb的javascript日期操作类库(XDate)
    提前防止Non-PIE错误,检测app是否包含PIE标志
    paip.数据库发邮件通知配置
    CADisplayLink 及定时器的使用
    HDU3415:Max Sum of Max-K-sub-sequence(单调队列)
  • 原文地址:https://www.cnblogs.com/dzswise/p/14907193.html
Copyright © 2011-2022 走看看