1

Updated question:

Would anyone be able to point me in the direction of any material that could help me to plot an optical flow map in python? Ideally i want to find something that provides a similar output to the video shown here: http://study.marearts.com/2014/04/opencv-study-calcopticalflowfarneback.html . Or something with a similar functional output

I have implemented the dense optical flow algorithm (cv2.calcOpticalFlowFarneback). And from this i have been able to sample the magnitudes at specified points of the image. The video feed that is being input is 640x480, and i have set sample points to be at every fifth pixel vertically and horizontally.

import cv2
import numpy as np
import matplotlib.pyplot as plt

cap = cv2.VideoCapture("T5.avi")

ret, frame1 = cap.read()

prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[..., 1] = 255

[R,C]=prvs.shape
count=0
while (1):
    ret, frame2 = cap.read()
    next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

    flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 2, 5, 1.2, 0)
    mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])

    RV=np.arange(5,480,5)
    CV=np.arange(5,640,5)
    # These give arrays of points to sample at increments of 5
    if count==0:
        count =1 #so that the following creation is only done once
        [Y,X]=np.meshgrid(CV,RV)
        # makes an x and y array of the points specified at sample increments

    temp =mag[np.ix_(RV,CV)]
    # this makes a temp array that stores the magnitude of flow at each of the sample points

    motionvectors=np.array((Y[:],X[:],Y[:]+temp.real[:],X[:]+temp.imag[:]))

    Ydist=motionvectors[0,:,:]- motionvectors[2,:,:]
    Xdist=motionvectors[1,:,:]- motionvectors[3,:,:]
    Xoriginal=X-Xdist
    Yoriginal=Y-Ydist



    plot2 = plt.figure()
    plt.quiver(Xoriginal, Yoriginal, X, Y,
               color='Teal',
               headlength=7)

    plt.title('Quiver Plot, Single Colour')
    plt.show(plot2)


    hsv[..., 0] = ang * 180 / np.pi / 2
    hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
    bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    cv2.imshow('frame2', bgr)

    k = cv2.waitKey(30) & 0xff

    if k == 27:
        break
    prvs = next

cap.release()
cv2.destroyAllWindows()

I think i have calculated the original and final X,Y positions of the pixels and the distances the moved and have put these into a matplotlib quiver plot.

The result i get does not coincide with the hsv plot of the dense optical flow (which i know to be correct as it was taken from the OpenCV tutorials) and the quiver plot also only shows one frame at a time and the plot must be exited before the next one displays.

Can anyone see where i have gone wrong in my calculations and how i can make the plot update automatically with each frame?

1 Answer 1

1

I do not know how to change the behaviour of matplotlib quiver plots, but I'm sure it is possible.

An alternative is to create a function to draw lines on top of the original image, based on the calculated optical flow. The following code should achieve this:

def dispOpticalFlow( Image,Flow,Divisor,name ):
"Display image with a visualisation of a flow over the top. A divisor controls the density of the quiver plot."
PictureShape = np.shape(Image)
#determine number of quiver points there will be
Imax = int(PictureShape[0]/Divisor)
Jmax = int(PictureShape[1]/Divisor)
#create a blank mask, on which lines will be drawn.
mask = np.zeros_like(Image)
for i in range(1, Imax):
  for j in range(1, Jmax):
     X1 = (i)*Divisor
     Y1 = (j)*Divisor
     X2 = int(X1 + Flow[X1,Y1,1])
     Y2 = int(Y1 + Flow[X1,Y1,0])
     X2 = np.clip(X2, 0, PictureShape[0])
     Y2 = np.clip(Y2, 0, PictureShape[1])
     #add all the lines to the mask
     mask = cv2.line(mask, (Y1,X1),(Y2,X2), [255, 255, 255], 1)
#superpose lines onto image
img = cv2.add(Image,mask)
#print image
cv2.imshow(name,img)
return []

This code only creates lines rather than arrows, but with some effort it could be modified to display arrows.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.