Python-OpenCV 处理视频(三)(四)(五): 标记运动轨迹 运动检测 运动方向判断

0x00. 光流

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

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

简单的实现流程:

  1. 加载一段视频。

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

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

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

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

代码示例:

 
  1. import cv2.cv as cv

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

  4.  
  5. nbFrames = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_COUNT))

  6. fps = cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FPS)

  7. wait = int(1/fps * 1000/1)

  8. width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))

  9. height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

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

  12. gray = cv.CreateImage((width,height), 8, 1) # Will hold the current frame

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

  15. currPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1) # idem at t

  16.  
  17. max_count = 500

  18. qLevel= 0.01

  19. minDist = 10

  20. prev_points = [] #Points at t-1

  21. curr_points = [] #Points at t

  22. lines=[] #To keep all the lines overtime

  23.  
  24. for f in xrange( nbFrames ):

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

  27.  
  28. cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray

  29. output = cv.CloneImage(frame)

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

  32.  
  33. #Calculate the movement using the previous and the current frame using the previous points

  34. 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)

  35.  
  36.  
  37. #If points status are ok and distance not negligible keep the point

  38. k = 0

  39. for i in range(len(curr_points)):

  40. nb = abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )

  41. if status[i] and nb > 2 :

  42. prev_points[k] = prev_points[i]

  43. curr_points[k] = curr_points[i]

  44. k += 1

  45.  
  46. prev_points = prev_points[:k]

  47. curr_points = curr_points[:k]

  48. #At the end only interesting points are kept

  49.  
  50. #Draw all the previously kept lines otherwise they would be lost the next frame

  51. for (pt1, pt2) in lines:

  52. cv.Line(frame, pt1, pt2, (255,255,255))

  53.  
  54. #Draw the lines between each points at t-1 and t

  55. for prevpoint, point in zip(prev_points,curr_points):

  56. prevpoint = (int(prevpoint[0]),int(prevpoint[1]))

  57. cv.Circle(frame, prevpoint, 15, 0)

  58. point = (int(point[0]),int(point[1]))

  59. cv.Circle(frame, point, 3, 255)

  60. cv.Line(frame, prevpoint, point, (255,255,255))

  61. lines.append((prevpoint,point)) #Append current lines to the lines list

  62.  
  63.  
  64. cv.Copy(gray, prev_gray) #Put the current frame prev_gray

  65. prev_points = curr_points

  66.  
  67. cv.ShowImage("The Video", frame)

  68. #cv.WriteFrame(writer, frame)

  69. cv.WaitKey(wait)

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

 
  1. import cv2.cv as cv

  2.  
  3. capture = cv.CaptureFromCAM(0)

  4.  
  5. width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))

  6. height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

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

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

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

  12. currPyr = cv.CreateImage((height / 3, width + 8), 8, cv.CV_8UC1) # idem at t

  13.  
  14. max_count = 500

  15. qLevel= 0.01

  16. minDist = 10

  17. prev_points = [] #Points at t-1

  18. curr_points = [] #Points at t

  19. lines=[] #To keep all the lines overtime

  20.  
  21. while True:

  22. frame = cv.QueryFrame(capture)

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

  24. output = cv.CloneImage(frame)

  25.  
  26. prev_points = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)

  27. 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)

  28.  
  29. #If points status are ok and distance not negligible keep the point

  30. k = 0

  31. for i in range(len(curr_points)):

  32. nb = abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )

  33. if status[i] and nb > 2 :

  34. prev_points[k] = prev_points[i]

  35. curr_points[k] = curr_points[i]

  36. k += 1

  37.  
  38. prev_points = prev_points[:k]

  39. curr_points = curr_points[:k]

  40. #At the end only interesting points are kept

  41.  
  42. #Draw all the previously kept lines otherwise they would be lost the next frame

  43. for (pt1, pt2) in lines:

  44. cv.Line(frame, pt1, pt2, (255,255,255))

  45.  
  46. #Draw the lines between each points at t-1 and t

  47. for prevpoint, point in zip(prev_points,curr_points):

  48. prevpoint = (int(prevpoint[0]),int(prevpoint[1]))

  49. cv.Circle(frame, prevpoint, 15, 0)

  50. point = (int(point[0]),int(point[1]))

  51. cv.Circle(frame, point, 3, 255)

  52. cv.Line(frame, prevpoint, point, (255,255,255))

  53. lines.append((prevpoint,point)) #Append current lines to the lines list

  54.  
  55.  
  56. cv.Copy(gray, prev_gray) #Put the current frame prev_gray

  57. prev_points = curr_points

  58.  
  59. cv.ShowImage("The Video", frame)

  60. #cv.WriteFrame(writer, frame)

  61. c = cv.WaitKey(1)

  62. if c == 27: #Esc on Windows

  63. break

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

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

直接加载视频:

 
  1. import cv2.cv as cv

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

  4.  
  5. #-- Informations about the video --

  6. nbFrames = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_COUNT))

  7. fps = cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FPS)

  8. wait = int(1/fps * 1000/1)

  9. width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))

  10. height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

  11. #For recording

  12. #codec = cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FOURCC)

  13. #writer=cv.CreateVideoWriter("img/output.avi", int(codec), int(fps), (width,height), 1) #Create writer with same parameters

  14. #----------------------------------

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

  17. gray = cv.CreateImage((width,height), 8, 1) # Will hold the current frame

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

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

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

  23.  
  24. max_count = 500

  25. qLevel= 0.01

  26. minDist = 10

  27.  
  28. begin = True

  29.  
  30. initial = []

  31. features = []

  32. prev_points = []

  33. curr_points = []

  34.  
  35. for f in xrange( nbFrames ):

  36.  
  37. frame = cv.QueryFrame(capture)

  38.  
  39. cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray

  40. cv.Copy(frame, output)

  41.  
  42.  
  43. if (len(prev_points) <= 10): #Try to get more points

  44. #Detect points on the image

  45. features = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)

  46. prev_points.extend(features) #Add the new points to list

  47. initial.extend(features) #Idem

  48.  
  49. if begin:

  50. cv.Copy(gray, prev_gray) #Now we have two frames to compare

  51. begin = False

  52.  
  53. #Compute movement

  54. 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)

  55.  
  56. #If points status are ok and distance not negligible keep the point

  57. k = 0

  58. for i in range(len(curr_points)):

  59. nb = abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )

  60. if status[i] and nb > 2 :

  61. initial[k] = initial[i]

  62. curr_points[k] = curr_points[i]

  63. k += 1

  64.  
  65. curr_points = curr_points[:k]

  66. initial = initial[:k]

  67. #At the end only interesting points are kept

  68.  
  69. #Draw the line between the first position of a point and the

  70. #last recorded position of the same point

  71. for i in range(len(curr_points)):

  72. cv.Line(output, (int(initial[i][0]),int(initial[i][1])), (int(curr_points[i][0]),int(curr_points[i][1])), (255,255,255))

  73. cv.Circle(output, (int(curr_points[i][0]),int(curr_points[i][1])), 3, (255,255,255))

  74.  
  75.  
  76. cv.Copy(gray, prev_gray)

  77. prev_points = curr_points

  78.  
  79.  
  80. cv.ShowImage("The Video", output)

  81. cv.WriteFrame(writer, output)

  82. cv.WaitKey(wait)

调用摄像头绘制:

 
  1. import cv2.cv as cv

  2.  
  3. capture = cv.CaptureFromCAM(0)

  4.  
  5. width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))

  6. height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

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

  9. gray = cv.CreateImage((width,height), 8, 1) # Will hold the current frame

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

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

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

  15.  
  16. max_count = 500

  17. qLevel= 0.01

  18. minDist = 10

  19.  
  20. begin = True

  21.  
  22. initial = []

  23. features = []

  24. prev_points = []

  25. curr_points = []

  26.  
  27. while True:

  28.  
  29. frame = cv.QueryFrame(capture)

  30.  
  31. cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) #Convert to gray

  32. cv.Copy(frame, output)

  33.  
  34.  
  35. if (len(prev_points) <= 10): #Try to get more points

  36. #Detect points on the image

  37. features = cv.GoodFeaturesToTrack(gray, None, None, max_count, qLevel, minDist)

  38. prev_points.extend(features) #Add the new points to list

  39. initial.extend(features) #Idem

  40.  
  41. if begin:

  42. cv.Copy(gray, prev_gray) #Now we have two frames to compare

  43. begin = False

  44.  
  45. #Compute movement

  46. 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)

  47.  
  48. #If points status are ok and distance not negligible keep the point

  49. k = 0

  50. for i in range(len(curr_points)):

  51. nb = abs( int(prev_points[i][0])-int(curr_points[i][0]) ) + abs( int(prev_points[i][1])-int(curr_points[i][1]) )

  52. if status[i] and nb > 2 :

  53. initial[k] = initial[i]

  54. curr_points[k] = curr_points[i]

  55. k += 1

  56.  
  57. curr_points = curr_points[:k]

  58. initial = initial[:k]

  59. for i in range(len(curr_points)):

  60. cv.Line(output, (int(initial[i][0]),int(initial[i][1])), (int(curr_points[i][0]),int(curr_points[i][1])), (255,255,255))

  61. cv.Circle(output, (int(curr_points[i][0]),int(curr_points[i][1])), 3, (255,255,255))

  62.  
  63.  
  64. cv.Copy(gray, prev_gray)

  65. prev_points = curr_points

  66.  
  67. cv.ShowImage("The Video", output)

  68. c = cv.WaitKey(1)

  69. if c == 27: #Esc on Windows

  70. break

 
  1.  
  2.  
 
  1.  
  2.  
 
  1.  
  2.  
————————————————————————————————————分割线来了————————————————————————————————————
 
 
 

0x00. 平均值法

通过计算两帧图像之间变化了的像素点占的百分比,来确定图像中是否有动作产生。

这里主要用到 Absdiff 函数,比较两帧图像之间有差异的点,当然需要将图像进行一些处理,例如平滑处理,灰度化处理,二值化处理,经过处理之后的二值图像上的点将更有效。

代码示例:

 
  1. import cv2.cv as cv

  2.  
  3. capture=cv.CaptureFromCAM(0)

  4.  
  5. frame1 = cv.QueryFrame(capture)

  6. frame1gray = cv.CreateMat(frame1.height, frame1.width, cv.CV_8U)

  7. cv.CvtColor(frame1, frame1gray, cv.CV_RGB2GRAY)

  8.  
  9. res = cv.CreateMat(frame1.height, frame1.width, cv.CV_8U)

  10.  
  11. frame2gray = cv.CreateMat(frame1.height, frame1.width, cv.CV_8U)

  12.  
  13. w= frame2gray.width

  14. h= frame2gray.height

  15. nb_pixels = frame2gray.width * frame2gray.height

  16.  
  17. while True:

  18. frame2 = cv.QueryFrame(capture)

  19. cv.CvtColor(frame2, frame2gray, cv.CV_RGB2GRAY)

  20.  
  21. cv.AbsDiff(frame1gray, frame2gray, res)

  22. cv.ShowImage("After AbsDiff", res)

  23.  
  24. cv.Smooth(res, res, cv.CV_BLUR, 5,5)

  25. element = cv.CreateStructuringElementEx(5*2+1, 5*2+1, 5, 5, cv.CV_SHAPE_RECT)

  26. cv.MorphologyEx(res, res, None, None, cv.CV_MOP_OPEN)

  27. cv.MorphologyEx(res, res, None, None, cv.CV_MOP_CLOSE)

  28. cv.Threshold(res, res, 10, 255, cv.CV_THRESH_BINARY_INV)

  29.  
  30. cv.ShowImage("Image", frame2)

  31. cv.ShowImage("Res", res)

  32.  
  33. #-----------

  34. nb=0

  35. for y in range(h):

  36. for x in range(w):

  37. if res[y,x] == 0.0:

  38. nb += 1

  39. avg = (nb*100.0)/nb_pixels

  40. #print "Average: ",avg, "%\r",

  41. if avg >= 5:

  42. print "Something is moving !"

  43. #-----------

  44.  
  45.  
  46. cv.Copy(frame2gray, frame1gray)

  47. c=cv.WaitKey(1)

  48. if c==27: #Break if user enters 'Esc'.

  49. break

0x01. 背景建模与前景检测

背景建模也是检测运动物体的一种办法,下面是代码示例:

 
  1. import cv2.cv as cv

  2.  
  3. capture = cv.CaptureFromCAM(0)

  4. width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))

  5. height = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT))

  6.  
  7. gray = cv.CreateImage((width,height), cv.IPL_DEPTH_8U, 1)

  8.  
  9. background = cv.CreateMat(height, width, cv.CV_32F)

  10. backImage = cv.CreateImage((width,height), cv.IPL_DEPTH_8U, 1)

  11. foreground = cv.CreateImage((width,height), cv.IPL_DEPTH_8U, 1)

  12. output = cv.CreateImage((width,height), 8, 1)

  13.  
  14. begin = True

  15. threshold = 10

  16.  
  17. while True:

  18. frame = cv.QueryFrame( capture )

  19.  
  20. cv.CvtColor(frame, gray, cv.CV_BGR2GRAY)

  21.  
  22. if begin:

  23. cv.Convert(gray, background) #Convert gray into background format

  24. begin = False

  25.  
  26. cv.Convert(background, backImage) #convert existing background to backImage

  27.  
  28. cv.AbsDiff(backImage, gray, foreground) #Absdiff to get differences

  29.  
  30. cv.Threshold(foreground, output, threshold, 255, cv.CV_THRESH_BINARY_INV)

  31.  
  32. cv.Acc(foreground, background,output) #Accumulate to background

  33.  
  34. cv.ShowImage("Output", output)

  35. cv.ShowImage("Gray", gray)

  36. c=cv.WaitKey(1)

  37. if c==27: #Break if user enters 'Esc'.

  38. break

0x02. 我的方法

上面的几种办法我都试了下,基本上能识别出运动的物体,但是发现总是有点瑕疵,所以又比对了几种别人的方案,然后合成了一个自己的方案:

具体处理思路:

  • 对两帧图像做一个absdiff得到新图像。

  • 对新图像做灰度和二值化处理。

  • 使用findContours函数获取二值化处理之后的图片中的轮廓。

  • 使用contourArea()过滤掉自己不想要的面积范围的轮廓。

这个办法基本上能够检测出物体的图像中物体的移动,而且我觉得通过设定contourArea()函数的过滤范围,可以检测距离摄像头不同距离范围的运动物体。

以下是代码示例:

 
  1. #!usr/bin/env python

  2. #coding=utf-8

  3.  
  4. import cv2

  5. import numpy as np

  6.  
  7. camera = cv2.VideoCapture(0)

  8. width = int(camera.get(3))

  9. height = int(camera.get(4))

  10.  
  11. firstFrame = None

  12.  
  13. while True:

  14. (grabbed, frame) = camera.read()

  15. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

  16. gray = cv2.GaussianBlur(gray, (21, 21), 0)

  17.  
  18. if firstFrame is None:

  19. firstFrame = gray

  20. continue

  21.  
  22. frameDelta = cv2.absdiff(firstFrame, gray)

  23. thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]

  24. # thresh = cv2.adaptiveThreshold(frameDelta,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\

  25. # cv2.THRESH_BINARY,11,2)

  26. # thresh = cv2.adaptiveThreshold(frameDelta,255,cv2.ADAPTIVE_THRESH_MEAN_C,\

  27. # cv2.THRESH_BINARY,11,2)

  28. thresh = cv2.dilate(thresh, None, iterations=2)

  29. (_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

  30. for c in cnts:

  31. if cv2.contourArea(c) < 10000:

  32. continue

  33. (x, y, w, h) = cv2.boundingRect(c)

  34.  
  35. cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

  36.  
  37. cv2.imshow("Security Feed", frame)

  38.  
  39. firstFrame = gray.copy()

  40. camera.release()

  41. cv2.destroyAllWindows()

 
 
——————————————————————————————————汪星人说这是分割线——————————————————————————————————
 
 
 
 

注意,我使用的OpenCV 版本是 3.0, 低版本就有可能出现第一条评论里的报错

在检测出运动的物体之后,我还需要知道运动的方向,使用了上一节中的办法检测运动我发现很难去计算运动方向,开始考虑通过计算轮廓的中点的变化来实现,但是因为每次检测出得轮廓的数量不稳定,所以这个办法会让误差不可控。

这时我发现了 goodFeaturesToTrack 函数,简直是救了我,goodFeaturesToTrack 函数可以获取图像中的最大特征值的角点,以下是我的思路:

Tips: 看代码之前请先看看我下面写的实现思路,另外还有代码里的注释也对于理解代码会有所帮助

  • 对两帧图像做一个 absdiff 得到新图像。

  • 对新图像做灰度和二值化处理。

  • 使用 goodFeaturesToTrack 函数得到最大特征值的角点。

  • 计算角点的平均点,写入队列。(通过计算平均点的解决办法类似物理中刚体问题抽象成质点解决的思路)

  • 维护一个长度为 10 的队列,队列满时计算队列中数据的增减情况,来确定运动方向。

代码示例(只实现了左右移动的判断):

 
  1. #!usr/bin/env python

  2. #coding=utf-8

  3.  
  4. import cv2

  5. import numpy as np

  6. import Queue

  7.  
  8. camera = cv2.VideoCapture(0)

  9. width = int(camera.get(3))

  10. height = int(camera.get(4))

  11.  
  12. firstFrame = None

  13. lastDec = None

  14. firstThresh = None

  15.  
  16. feature_params = dict( maxCorners = 100,

  17. qualityLevel = 0.3,

  18. minDistance = 7,

  19. blockSize = 7 )

  20.  
  21. lk_params = dict( winSize = (15,15),

  22. maxLevel = 2,

  23. criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

  24.  
  25. color = np.random.randint(0,255,(100,3))

  26. num = 0

  27.  
  28. q_x = Queue.Queue(maxsize = 10)

  29. q_y = Queue.Queue(maxsize = 10)

  30.  
  31. while True:

  32. (grabbed, frame) = camera.read()

  33. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

  34. gray = cv2.GaussianBlur(gray, (21, 21), 0)

  35.  
  36. if firstFrame is None:

  37. firstFrame = gray

  38. continue

  39.  
  40. # 对两帧图像进行 absdiff 操作

  41. frameDelta = cv2.absdiff(firstFrame, gray)

  42. # diff 之后的图像进行二值化

  43. thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]

  44. # 下面的是几种不同的二值化的方法,感觉对我来说效果都差不多

  45. # thresh = cv2.adaptiveThreshold(frameDelta,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\

  46. # cv2.THRESH_BINARY,11,2)

  47. # thresh = cv2.adaptiveThreshold(frameDelta,255,cv2.ADAPTIVE_THRESH_MEAN_C,\

  48. # cv2.THRESH_BINARY,11,2)

  49. thresh = cv2.dilate(thresh, None, iterations=2)

  50. # 识别角点

  51. p0 = cv2.goodFeaturesToTrack(thresh, mask = None, **feature_params)

  52. if p0 is not None:

  53. x_sum = 0

  54. y_sum = 0

  55. for i, old in enumerate(p0):

  56. x, y = old.ravel()

  57. x_sum += x

  58. y_sum += y

  59. # 计算出所有角点的平均值

  60. x_avg = x_sum / len(p0)

  61. y_avg = y_sum / len(p0)

  62.  
  63. # 写入固定长度的队列

  64. if q_x.full():

  65. # 如果队列满了,就计算这个队列中元素的增减情况

  66. qx_list = list(q_x.queue)

  67. key = 0

  68. diffx_sum = 0

  69. for item_x in qx_list:

  70. key +=1

  71. if key < 10:

  72. # 下一个元素减去上一个元素

  73. diff_x = item_x - qx_list[key]

  74. diffx_sum += diff_x

  75. # 加和小于0,表明队列中的元素在递增

  76. if diffx_sum < 0:

  77. print "left"

  78. cv2.putText(frame, "some coming form left", (100,100), 0, 0.5, (0,0,255),2)

  79. else:

  80. print "right"

  81.  
  82. print x_avg

  83. q_x.get()

  84. q_x.put(x_avg)

  85. cv2.putText(frame, str(x_avg), (300,100), 0, 0.5, (0,0,255),2)

  86. frame = cv2.circle(frame,(int(x_avg),int(y_avg)),5,color[i].tolist(),-1)

  87.  
  88. cv2.imshow("Security Feed", frame)

  89. firstFrame = gray.copy()

  90.  
  91. camera.release()

  92. cv2.destroyAllWindows()

总的来讲作为一个图像处理的小白,不断地折腾和尝试,终于搞出了自己想要的东西,OpenCV绝对是喜欢折腾的人必要掌握的一个库了,以后肯定还会继续研究这块东西。

 
from: https://segmentfault.com/a/1190000003804820
https://segmentfault.com/a/1190000003804835
https://segmentfault.com/a/1190000003804867

猜你喜欢

转载自blog.csdn.net/qq_42393859/article/details/84862291
今日推荐