Python-OpenCV 处理视频(三): 标记运动轨迹

0x00. 光流

光流是进行视频中运动对象轨迹标记的一种很常用的方法,在OpenCV中实现光流也很容易。

CalcOpticalFlowPyrLK 函数计算一个稀疏特征集的光流,使用金字塔中的迭代 Lucas-Kanade 方法。

简单的实现流程:

  1. 加载一段视频。

  2. 调用GoodFeaturesToTrack函数寻找兴趣点。

  3. 调用CalcOpticalFlowPyrLK函数计算出两帧图像中兴趣点的移动情况。

  4. 删除未移动的兴趣点。

  5. 在两次移动的点之间绘制一条线段。

代码示例:

import cv2.cv as cv

capture = cv.CaptureFromFile('img/myvideo.avi')

nbFrames = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_COUNT))
fps = cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FPS)
wait = int(1/fps * 1000/1)
width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

prev_gray = cv.CreateImage((width,height), 8, 1) #Will hold the frame at t-1
gray = cv.CreateImage((width,height), 8, 1) # Will hold the current frame

prevPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1) #Will hold the pyr frame at t-1
currPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1) # idem at t

max_count = 500
qLevel= 0.01
minDist = 10
prev_points = [] #Points at t-1
curr_points = [] #Points at t
lines=[] #To keep all the lines overtime

for f in xrange( nbFrames ):

    frame = cv.QueryFrame(capture) #Take a frame of the video

    cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray
    output = cv.CloneImage(frame)

    prev_points = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist) #Find points on the image

    #Calculate the movement using the previous and the current frame using the previous points
    curr_points, status, err = cv.CalcOpticalFlowPyrLK(prev_gray, gray, prevPyr, currPyr, prev_points, (10, 10), 3, (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS,20, 0.03), 0)


    #If points status are ok and distance not negligible keep the point
    k = 0
    for i in range(len(curr_points)):
        nb =  abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )
        if status[i] and  nb > 2 :
            prev_points[k] = prev_points[i]
            curr_points[k] = curr_points[i]
            k += 1

    prev_points = prev_points[:k]
    curr_points = curr_points[:k]
    #At the end only interesting points are kept

    #Draw all the previously kept lines otherwise they would be lost the next frame
    for (pt1, pt2) in lines:
        cv.Line(frame, pt1, pt2, (255,255,255))

    #Draw the lines between each points at t-1 and t
    for prevpoint, point in zip(prev_points,curr_points):
        prevpoint = (int(prevpoint[0]),int(prevpoint[1]))
        cv.Circle(frame, prevpoint, 15, 0)
        point = (int(point[0]),int(point[1]))
        cv.Circle(frame, point, 3, 255)
        cv.Line(frame, prevpoint, point, (255,255,255))
        lines.append((prevpoint,point)) #Append current lines to the lines list


    cv.Copy(gray, prev_gray) #Put the current frame prev_gray
    prev_points = curr_points

    cv.ShowImage("The Video", frame)
    #cv.WriteFrame(writer, frame)
    cv.WaitKey(wait)

直接调用摄像头使用该方法:

import cv2.cv as cv

capture = cv.CaptureFromCAM(0)

width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

prev_gray = cv.CreateImage((width,height), 8, 1)
gray = cv.CreateImage((width,height), 8, 1)

prevPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1) #Will hold the pyr frame at t-1
currPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1) # idem at t

max_count = 500
qLevel= 0.01
minDist = 10
prev_points = [] #Points at t-1
curr_points = [] #Points at t
lines=[] #To keep all the lines overtime

while True:
    frame = cv.QueryFrame(capture)
    cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray
    output = cv.CloneImage(frame)

    prev_points = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)
    curr_points, status, err = cv.CalcOpticalFlowPyrLK(prev_gray, gray, prevPyr, currPyr, prev_points, (10, 10), 3, (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS,20, 0.03), 0)

    #If points status are ok and distance not negligible keep the point
    k = 0
    for i in range(len(curr_points)):
        nb =  abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )
        if status[i] and  nb > 2 :
            prev_points[k] = prev_points[i]
            curr_points[k] = curr_points[i]
            k += 1

    prev_points = prev_points[:k]
    curr_points = curr_points[:k]
    #At the end only interesting points are kept

    #Draw all the previously kept lines otherwise they would be lost the next frame
    for (pt1, pt2) in lines:
        cv.Line(frame, pt1, pt2, (255,255,255))

    #Draw the lines between each points at t-1 and t
    for prevpoint, point in zip(prev_points,curr_points):
        prevpoint = (int(prevpoint[0]),int(prevpoint[1]))
        cv.Circle(frame, prevpoint, 15, 0)
        point = (int(point[0]),int(point[1]))
        cv.Circle(frame, point, 3, 255)
        cv.Line(frame, prevpoint, point, (255,255,255))
        lines.append((prevpoint,point)) #Append current lines to the lines list


    cv.Copy(gray, prev_gray) #Put the current frame prev_gray
    prev_points = curr_points

    cv.ShowImage("The Video", frame)
    #cv.WriteFrame(writer, frame)
    c = cv.WaitKey(1)
    if c == 27: #Esc on Windows
        break

0x01. 寻找最大特征值的角点

cv.GoodFeaturesToTrack 函数可以检测出图像中最大特征值的角点,使用这个函数可以对图像中的特征点进行跟踪,从而绘制出运动轨迹。

直接加载视频:

import cv2.cv as cv

capture = cv.CaptureFromFile('img/myvideo.avi')

#-- Informations about the video --
nbFrames = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_COUNT))
fps = cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FPS)
wait = int(1/fps * 1000/1)
width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))
#For recording
#codec = cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FOURCC)
#writer=cv.CreateVideoWriter("img/output.avi", int(codec), int(fps), (width,height), 1) #Create writer with same parameters
#----------------------------------

prev_gray = cv.CreateImage((width,height), 8, 1) #Will hold the frame at t-1
gray = cv.CreateImage((width,height), 8, 1) # Will hold the current frame

output = cv.CreateImage((width,height), 8, 3)

prevPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1)
currPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1)

max_count = 500
qLevel= 0.01
minDist = 10

begin = True

initial = []
features = []
prev_points = []
curr_points = []

for f in xrange( nbFrames ):

    frame = cv.QueryFrame(capture)

    cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray
    cv.Copy(frame, output)


    if (len(prev_points) <= 10): #Try to get more points
        #Detect points on the image
        features = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)
        prev_points.extend(features) #Add the new points to list
        initial.extend(features) #Idem

    if begin:
        cv.Copy(gray, prev_gray) #Now we have two frames to compare
        begin = False

    #Compute movement
    curr_points, status, err = cv.CalcOpticalFlowPyrLK(prev_gray, gray, prevPyr, currPyr, prev_points, (10, 10), 3, (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS,20, 0.03), 0)

    #If points status are ok and distance not negligible keep the point
    k = 0
    for i in range(len(curr_points)):
        nb =  abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )
        if status[i] and  nb > 2 :
            initial[k] = initial[i]
            curr_points[k] = curr_points[i]
            k += 1

    curr_points = curr_points[:k]
    initial = initial[:k]
    #At the end only interesting points are kept

    #Draw the line between the first position of a point and the
    #last recorded position of the same point
    for i in range(len(curr_points)):
        cv.Line(output, (int(initial[i][0]),int(initial[i][1])), (int(curr_points[i][0]),int(curr_points[i][1])), (255,255,255))
        cv.Circle(output, (int(curr_points[i][0]),int(curr_points[i][1])), 3, (255,255,255))


    cv.Copy(gray, prev_gray)
    prev_points = curr_points


    cv.ShowImage("The Video",  output)
    cv.WriteFrame(writer, output)
    cv.WaitKey(wait)

调用摄像头绘制:

import cv2.cv as cv

capture = cv.CaptureFromCAM(0)

width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

prev_gray = cv.CreateImage((width,height), 8, 1) #Will hold the frame at t-1
gray = cv.CreateImage((width,height), 8, 1) # Will hold the current frame

output = cv.CreateImage((width,height), 8, 3)

prevPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1)
currPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1)

max_count = 500
qLevel= 0.01
minDist = 10

begin = True

initial = []
features = []
prev_points = []
curr_points = []

while True:

    frame = cv.QueryFrame(capture)

    cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray
    cv.Copy(frame, output)


    if (len(prev_points) <= 10): #Try to get more points
        #Detect points on the image
        features = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)
        prev_points.extend(features) #Add the new points to list
        initial.extend(features) #Idem

    if begin:
        cv.Copy(gray, prev_gray) #Now we have two frames to compare
        begin = False

    #Compute movement
    curr_points, status, err = cv.CalcOpticalFlowPyrLK(prev_gray, gray, prevPyr, currPyr, prev_points, (10, 10), 3, (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS,20, 0.03), 0)

    #If points status are ok and distance not negligible keep the point
    k = 0
    for i in range(len(curr_points)):
        nb =  abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )
        if status[i] and  nb > 2 :
            initial[k] = initial[i]
            curr_points[k] = curr_points[i]
            k += 1

    curr_points = curr_points[:k]
    initial = initial[:k]
    for i in range(len(curr_points)):
        cv.Line(output, (int(initial[i][0]),int(initial[i][1])), (int(curr_points[i][0]),int(curr_points[i][1])), (255,255,255))
        cv.Circle(output, (int(curr_points[i][0]),int(curr_points[i][1])), 3, (255,255,255))


    cv.Copy(gray, prev_gray)
    prev_points = curr_points

    cv.ShowImage("The Video", output)
    c = cv.WaitKey(1)
    if c == 27: #Esc on Windows
        break
  • 2
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Python-opencv是一个使用Python进行图像处理和计算机视觉的库。运动方向判断是指通过分析视频物体或者人的运动轨迹来判断其运动的方向。运动方向判断可以在很多应用使用,比如行人检测、车辆跟踪等。 在这个.rar文件,你可以找到一些使用Python-opencv处理视频运动方向判断的示例代码和一些视频样本。通过运行这些示例代码,你可以学习如何使用Python-opencv来实现运动方向判断的功能。 Python-opencv处理视频的基本步骤包括读取视频、获取每一帧图像、预处理图像、计算运动方向等。首先,使用cv2.VideoCapture函数读取视频文件。然后,使用while循环遍历每一帧图像,并对每一帧进行预处理,比如转换成灰度图像、平滑处理等。接下来,使用cv2.absdiff函数计算当前帧和上一帧之间的差别,通过阈值化处理得到前景图像。然后,可以使用cv2.findContours函数找出前景图像的轮廓,进一步筛选出运动物体的轮廓。最后,计算轮廓的心点坐标并与上一帧的心点坐标进行比较,从而判断运动方向。 通过这些步骤,我们可以实现对视频运动方向的判断。当然,这只是一个简单的示例,实际应用可能需要更复杂的算法和处理步骤。但是通过学习这个.rar文件的代码和示例,你可以了解到使用Python-opencv处理视频运动方向判断的基本方法,同时也可以根据自己的需求进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值