注意,我使用的OpenCV 版本是 3.0, 低版本就有可能出现第一条评论里的报错
在检测出运动的物体之后,我还需要知道运动的方向,使用了上一节中的办法检测运动我发现很难去计算运动方向,开始考虑通过计算轮廓的中点的变化来实现,但是因为每次检测出得轮廓的数量不稳定,所以这个办法会让误差不可控。
这时我发现了 goodFeaturesToTrack
函数,简直是救了我,goodFeaturesToTrack
函数可以获取图像中的最大特征值的角点,以下是我的思路:
Tips: 看代码之前请先看看我下面写的实现思路,另外还有代码里的注释也对于理解代码会有所帮助
absdiff
得到新图像。goodFeaturesToTrack
函数得到最大特征值的角点。代码示例(只实现了左右移动的判断):
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 | #!usr/bin/env python#coding=utf-8 import cv2import numpy as npimport Queue camera = cv2.VideoCapture(0)width = int(camera.get(3))height = int(camera.get(4)) firstFrame = NonelastDec = NonefirstThresh = None feature_params = dict( maxCorners = 100, qualityLevel = 0.3, minDistance = 7, blockSize = 7 ) lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) color = np.random.randint(0,255,(100,3))num = 0 q_x = Queue.Queue(maxsize = 10)q_y = Queue.Queue(maxsize = 10) while True: (grabbed, frame) = camera.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (21, 21), 0) if firstFrame is None: firstFrame = gray continue # 对两帧图像进行 absdiff 操作 frameDelta = cv2.absdiff(firstFrame, gray) # diff 之后的图像进行二值化 thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1] # 下面的是几种不同的二值化的方法,感觉对我来说效果都差不多 # thresh = cv2.adaptiveThreshold(frameDelta,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\\ # cv2.THRESH_BINARY,11,2) # thresh = cv2.adaptiveThreshold(frameDelta,255,cv2.ADAPTIVE_THRESH_MEAN_C,\\ # cv2.THRESH_BINARY,11,2) thresh = cv2.dilate(thresh, None, iterations=2) # 识别角点 p0 = cv2.goodFeaturesToTrack(thresh, mask = None, **feature_params) if p0 is not None: x_sum = 0 y_sum = 0 for i, old in enumerate(p0): x, y = old.ravel() x_sum += x y_sum += y # 计算出所有角点的平均值 x_avg = x_sum / len(p0) y_avg = y_sum / len(p0) # 写入固定长度的队列 if q_x.full(): # 如果队列满了,就计算这个队列中元素的增减情况 qx_list = list(q_x.queue) key = 0 diffx_sum = 0 for item_x in qx_list: key +=1 if key < 10: # 下一个元素减去上一个元素 diff_x = item_x – qx_list[key] diffx_sum += diff_x # 加和小于0,表明队列中的元素在递增 if diffx_sum < 0: print \”left\” cv2.putText(frame, \”some coming form left\”, (100,100), 0, 0.5, (0,0,255),2) else: print \”right\” print x_avg q_x.get() q_x.put(x_avg) cv2.putText(frame, str(x_avg), (300,100), 0, 0.5, (0,0,255),2) frame = cv2.circle(frame,(int(x_avg),int(y_avg)),5,color[i].tolist(),–1) cv2.imshow(\”Security Feed\”, frame) firstFrame = gray.copy() camera.release()cv2.destroyAllWindows() |
总的来讲作为一个图像处理的小白,不断地折腾和尝试,终于搞出了自己想要的东西,OpenCV绝对是喜欢折腾的人必要掌握的一个库了,以后肯定还会继续研究这块东西。