# 第三周-02-运动估计-芥末酱-201906 **Repository Path**: jiemoChen/03st-02-week-JieMoJiang-201906 ## Basic Information - **Project Name**: 第三周-02-运动估计-芥末酱-201906 - **Description**: 1. 在测试视频(OpenCV安装目录\sources\samples\data)上,使用基于混合高斯模型的背景提取算法,提取前景并显示(显示二值化图像,前景为白色)。 2. 在1基础上,将前景目标进行分割,进一步使用不同颜色矩形框标记,并在命令行窗口中输出每个矩形框的位置和大小。 3. 安装ImageWatch,并在代码中通过设置断点,观察处理中间结果图像。 扩展: 4. 使用光流估计方法,在前述测试视频上计算特征点,进一步进行特征点光流估计。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2019-06-25 - **Last Updated**: 2022-05-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 第三周-02-运动估计-芥末酱-201906 #### 介绍 1. 在测试视频(OpenCV安装目录\sources\samples\data)上,使用基于混合高斯模型的背景提取算法,提取前景并显示(显示二值化图像,前景为白色)。 2. 在1基础上,将前景目标进行分割,进一步使用不同颜色矩形框标记,并在命令行窗口中输出每个矩形框的位置和大小。 3. 安装ImageWatch,并在代码中通过设置断点,观察处理中间结果图像。 扩展: 4. 使用光流估计方法,在前述测试视频上计算特征点,进一步进行特征点光流估计。 # 1. 在测试视频(OpenCV安装目录\sources\samples\data)上,使用基于混合高斯模型的背景提取算法,提取前景并显示(显示二值化图像,前景为白色)。 ``` import cv2 import numpy as np cap=cv2.VideoCapture('vtest.avi') kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)) fgbg=cv2.createBackgroundSubtractorMOG2()# 实例化混合高斯模型 #fgbg=cv2.createBackgroundSubtractorKNN(detectShadows=True) count=0 while(True): ret,frame=cap.read() fgmask=fgbg.apply(frame) fgmask=cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)# 开运算,去噪点。 rect,contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 在二值图像上检测物体轮廓 for c in contours: Area=cv2.contourArea(c)# 面积 if Area<300:# 过滤操作 continue count+=1 print("{}-prospect:{}".format(count,Area),end=" ") #打印出每个前景的面积 x,y,w,h=cv2.boundingRect(c) print("x:{} y:{}".format(x,y))#打印坐标 cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)# 在原图上画外接矩形 cv2.putText(frame, str(count), (x,y), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0,225,0), 1)# 在前景框上标上编号 cv2.putText(frame, "count:", (5, 20), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 255, 0), 1) #显示总数 cv2.putText(frame, str(count), (75, 20), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 255, 0), 1) print("----------------------------") #cv2.getBackgroundImage cv2.resizeWindow("frame", 700, 500 ) cv2.resizeWindow("fgmask", 700, 500 ) cv2.imshow('frame',frame)# 显示每一帧图像 cv2.imshow('fgmask', fgmask)# 显示每一帧图像对应的前景提取结果 k = cv2.waitKey(150) & 0xff# 控制视频播放速度 if k == 27: break cap.release() cv2.destroyAllWindows() ``` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0625/203723_f122b819_5009451.png "屏幕截图.png") # 2. 在1基础上,将前景目标进行分割,进一步使用不同颜色矩形框标记,并在命令行窗口中输出每个矩形框的位置和大小。 output:以下是部分结果 ``` 3422-prospect:3709.0 x:52 y:173 3423-prospect:804.0 x:594 y:118 ---------------------------- 3424-prospect:7044.5 x:476 y:191 3425-prospect:3906.5 x:272 y:183 3426-prospect:3811.0 x:46 y:171 3427-prospect:791.5 x:596 y:117 3428-prospect:322.5 x:726 y:55 ---------------------------- 3429-prospect:6979.5 x:474 y:190 3430-prospect:4034.5 x:272 y:184 3431-prospect:3894.5 x:42 y:174 3432-prospect:820.0 x:598 y:117 3433-prospect:316.5 x:728 y:59 ---------------------------- 3434-prospect:2073.5 x:106 y:226 3435-prospect:1827.0 x:472 y:192 3436-prospect:4477.0 x:527 y:189 3437-prospect:4139.0 x:272 y:185 3438-prospect:1708.0 x:41 y:174 3439-prospect:929.5 x:600 y:116 3440-prospect:351.5 x:730 y:56 ---------------------------- 3441-prospect:1953.0 x:107 y:224 3442-prospect:1694.5 x:466 y:189 3443-prospect:4410.5 x:519 y:188 3444-prospect:4133.0 x:272 y:187 3445-prospect:1590.5 x:40 y:172 3446-prospect:933.0 x:600 y:116 3447-prospect:433.0 x:730 y:54 ---------------------------- 3448-prospect:2019.5 x:108 y:224 3449-prospect:1897.0 x:459 y:189 3450-prospect:4215.5 x:272 y:189 3451-prospect:3944.0 x:530 y:187 3452-prospect:1569.0 x:36 y:170 3453-prospect:958.5 x:600 y:117 3454-prospect:435.5 x:731 y:54 ---------------------------- 3455-prospect:2027.5 x:111 y:223 3456-prospect:4168.0 x:267 y:190 3457-prospect:2065.0 x:448 y:189 3458-prospect:3558.0 x:546 y:188 3459-prospect:1624.0 x:32 y:170 3460-prospect:944.0 x:602 y:116 3461-prospect:442.5 x:733 y:56 ---------------------------- ``` # 3. 安装ImageWatch,并在代码中通过设置断点,观察处理中间结果图像。 cv2.calcOpticalFlowPyrLK(): 参数: prevImage 前一帧图像 nextImage 当前帧图像 prevPts 待跟踪的特征点向量 winSize 搜索窗口的大小 maxLevel 最大的金字塔层数 返回: nextPts 输出跟踪特征点向量 status 特征点是否找到,找到的状态为1,未找到的状态为0 # 扩展:4. 使用光流估计方法,在前述测试视频上计算特征点,进一步进行特征点光流估计。 ``` import cv2 import numpy as np cap=cv2.VideoCapture('images/test.avi') # 角点检测所需参数,在进行光流估计计算之前,需要先进行角点检测,然后再把检测出的特征点进行光流估计。 feature_params = dict( maxCorners = 100, qualityLevel = 0.3, minDistance = 7) # lucas kanade参数 lk_params = dict( winSize = (15,15), maxLevel = 2) # 随机颜色条 color = np.random.randint(0,255,(100,3)) # 拿到第一帧图像,这里没有循环。 ret,old_frame=cap.read() old_gray=cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY) # 返回所有检测特征点,第一个参数输入图像,maxCorners:角点最大数量(效率),qualityLevel:品质因子(特征值越大的越好,来筛选) # minDistance:距离,相当于这区间有比这个角点强的,就不要这个弱的了。 P0=cv2.goodFeaturesToTrack(old_gray,mask=None,**feature_params)# 获取图像中最好的角点特征,None表示在整幅图上寻找角点。 print(P0.shape)# # 创建一个mask mask=np.zeros_like(old_frame) while (True): ret,frame=cap.read() frame_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # 需要传入前一帧和当前图像以及前一帧检测到的角点 p1, st, err=cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,P0,None,**lk_params) good_new=p1[st==1]#st=1当前帧图像检测到了上一阵的角点特征,shape为(38,2),2表示坐标值 good_old=P0[st==1] # 绘制轨迹 for i,(new,old)in enumerate (zip(good_new,good_old)): a,b = new.ravel()# 新坐标 c,d = old.ravel()# 旧坐标 mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)# 直线的起点(a,b),直线的终点坐标(c,d) frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1) img=cv2.add(frame,mask) cv2.imshow('frame',img) k = cv2.waitKey(150) & 0xff if k == 27: break # 更新 old_gray = frame_gray.copy() P0 = good_new.reshape(-1,1,2) cv2.destroyAllWindows() cap.release() ``` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0625/204150_25df9337_5009451.png "屏幕截图.png") 运动轨迹光流估计结果图