Python-OpenCV 处理视频(三): 标记运动轨迹
生活随笔
收集整理的這篇文章主要介紹了
Python-OpenCV 处理视频(三): 标记运动轨迹
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
0x00. 光流
光流是進行視頻中運動對象軌跡標記的一種很常用的方法,在OpenCV中實現光流也很容易。
CalcOpticalFlowPyrLK 函數計算一個稀疏特征集的光流,使用金字塔中的迭代 Lucas-Kanade 方法。
簡單的實現流程:
加載一段視頻。
調用GoodFeaturesToTrack函數尋找興趣點。
調用CalcOpticalFlowPyrLK函數計算出兩幀圖像中興趣點的移動情況。
刪除未移動的興趣點。
在兩次移動的點之間繪制一條線段。
代碼示例:
import cv2.cv as cvcapture = 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 frameprevPyr = 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 tmax_count = 500 qLevel= 0.01 minDist = 10 prev_points = [] #Points at t-1 curr_points = [] #Points at t lines=[] #To keep all the lines overtimefor f in xrange( nbFrames ):frame = cv.QueryFrame(capture) #Take a frame of the videocv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to grayoutput = 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 pointscurr_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 pointk = 0for 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 += 1prev_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 framefor (pt1, pt2) in lines:cv.Line(frame, pt1, pt2, (255,255,255))#Draw the lines between each points at t-1 and tfor 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 listcv.Copy(gray, prev_gray) #Put the current frame prev_grayprev_points = curr_pointscv.ShowImage("The Video", frame)#cv.WriteFrame(writer, frame)cv.WaitKey(wait)直接調用攝像頭使用該方法:
import cv2.cv as cvcapture = 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 tmax_count = 500 qLevel= 0.01 minDist = 10 prev_points = [] #Points at t-1 curr_points = [] #Points at t lines=[] #To keep all the lines overtimewhile True:frame = cv.QueryFrame(capture)cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to grayoutput = 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 pointk = 0for 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 += 1prev_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 framefor (pt1, pt2) in lines:cv.Line(frame, pt1, pt2, (255,255,255))#Draw the lines between each points at t-1 and tfor 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 listcv.Copy(gray, prev_gray) #Put the current frame prev_grayprev_points = curr_pointscv.ShowImage("The Video", frame)#cv.WriteFrame(writer, frame)c = cv.WaitKey(1)if c == 27: #Esc on Windowsbreak0x01. 尋找最大特征值的角點
cv.GoodFeaturesToTrack 函數可以檢測出圖像中最大特征值的角點,使用這個函數可以對圖像中的特征點進行跟蹤,從而繪制出運動軌跡。
直接加載視頻:
import cv2.cv as cvcapture = 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 frameoutput = 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 = 10begin = Trueinitial = [] features = [] prev_points = [] curr_points = []for f in xrange( nbFrames ):frame = cv.QueryFrame(capture)cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to graycv.Copy(frame, output)if (len(prev_points) <= 10): #Try to get more points#Detect points on the imagefeatures = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)prev_points.extend(features) #Add the new points to listinitial.extend(features) #Idemif begin:cv.Copy(gray, prev_gray) #Now we have two frames to comparebegin = False#Compute movementcurr_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 pointk = 0for 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 += 1curr_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 pointfor 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_pointscv.ShowImage("The Video", output)cv.WriteFrame(writer, output)cv.WaitKey(wait)調用攝像頭繪制:
import cv2.cv as cvcapture = 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 frameoutput = 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 = 10begin = Trueinitial = [] features = [] prev_points = [] curr_points = []while True:frame = cv.QueryFrame(capture)cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to graycv.Copy(frame, output)if (len(prev_points) <= 10): #Try to get more points#Detect points on the imagefeatures = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)prev_points.extend(features) #Add the new points to listinitial.extend(features) #Idemif begin:cv.Copy(gray, prev_gray) #Now we have two frames to comparebegin = False#Compute movementcurr_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 pointk = 0for 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 += 1curr_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_pointscv.ShowImage("The Video", output)c = cv.WaitKey(1)if c == 27: #Esc on Windowsbreak總結
以上是生活随笔為你收集整理的Python-OpenCV 处理视频(三): 标记运动轨迹的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python-OpenCV 处理视频(二
- 下一篇: Python-OpenCV 处理视频(四