1. 光流法
光流:由于目标对象或者摄像机的移动造成的图像对象在连续两帧图像中的移动被称为光流。它是一个 2D 向量场,可以用来显示一个点从第一帧图像到第二 帧图像之间的移动。
光流是基于一下假设的:
结果:提取运动的物体
import cv2
import numpy as np
cap = cv2.VideoCapture("vtest.avi")
# 取出视频的第一帧
ret, frame1 = cap.read()
prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1) # 为绘制创建掩码图片
hsv[...,1] = 255
while(1):
ret, frame2 = cap.read()
next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY) #转为灰度图
flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0) # 计算光流以获取点的新位置
# 色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°
# 饱和度S:取值范围为0.0~1.0
# 亮度V:取值范围为0.0(黑色)~1.0(白色)
mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
hsv[...,0] = ang*180/np.pi/2 #色调范围:0°~360°
hsv[...,2] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX)
rgb = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)
cv2.imshow('frame2',rgb)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
elif k == ord('s'):
cv2.imwrite('opticalfb.png',frame2)
cv2.imwrite('opticalhsv.png',rgb)
prvs = next
cap.release()
cv2.destroyAllWindows()
结果:移动的物体会被标记为白色,背景会被标记为黑色的
import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
fgbg = cv2.createBackgroundSubtractorMOG2() #背景分割
while(1):
ret, frame = cap.read()
fgmask = fgbg.apply(frame) #应用
cv2.imshow('frame',fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
3.腐蚀和膨胀(开运算和闭运算)
1)腐蚀: cv2.erode()
作会把前景物体的边界腐蚀掉(但是前景仍然是白色)。这是怎么做到的呢?卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是 1,那么中心元素就保持原来的像素值,否则就变为零。 ------去噪声
2)膨胀: cv2.dilate()
与卷积核对应的原图像的像素值中只要有一个是 1,中心元 素的像素值就是 1。所以这个操作会增加图像中的白色区域(前景)。--------连接两个分开的物体。
3)开运算: cv2.morphologyEx()
先进性腐蚀再进行膨胀就叫做开运算。因为腐蚀在去掉白噪声的同时,也会使前景对象变小。所以我们再对他进行膨胀。这时噪声已经被去除了,不会再回来了,但是前景还在并会增加。
4)闭运算:
先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的 小黑点。
代码:
import cv2
import numpy as np
img = cv2.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1) #腐蚀
dilation = cv2.dilate(img,kernel,iterations = 1) #膨胀
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) #开运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) #闭运算