在OpenCV中我们要获取一个视频,需要创建一个VideoCapture对象,指定你呀读取的视频文件:
(1)创建读取视频的对象
cap=cv2.VideoCapture(filepath)
参数:
filepath:视频文件路径
(2)视频的属性信息
2.1 获取视频的某些属性信息
retval=cap.get(proId)
参数:
proId:从0到18的数字,每个数字表示视频的属性
2.2 修改视频的某些属性信息
cap.set(proId,value)
参数:
proid:属性的索引,与上面的表格相对应
value:修改后的属性值
(3)判断图像是否读取成功
isornot=cap.isOpened()
(4)获取视频的一帧图像
ret,frame=cap.read()
参数:
ret:若获取成功返回true,获取失败,返回false
Frame:获取到某一帧的图像
(5)显示视频图像
调用cv2.imshow()显示图像,在显示图像时使用cv2.waitkey()设置适当的持续时间,如果太低视频会播放的非常慢,通常设置25ms就可以了。
(6)调用cap.realease()将视频释放掉
import numpy
import cv2
# 1 读取视频
cap=cv2.VideoCapture('Dog.wmv')
# 2 获取每一帧图像
while (cap.isOpened()):
# 3 获取每一幅图像
ret,frame=cap.read()
# 4 是否获取成功
if ret==True:
cv2.imshow('frame',frame)
# 5 每一帧视频的显示时间为25ms
# 6 释放视频对象
cap.release()
cv2.destroyAllWindows()
在OpenCV中保存视频使用的是VedioWrite对象,在其中指定输出文件的名称:
(1)创建视频写入对象
out=cv2.VideoWriter(filename,fourcc,fps,frameSize)
参数:
filename:视频保存的为宗旨
fourcc:指定视频编码器的4字节代码
fps:帧率
frameSize:帧大小
设置视频的编码解码器
retval=cv2.VideoWriter_fourcc(c1,c2,c3,c4)
(2)利用cap.read()获取视频中的每一帧图像
(3)使用out.write()将某一帧图像写入视频
(4)使用cap.release()和out.rease()释放资源
import numpy
import cv2
# 1 读取视频
cap=cv2.VideoCapture('Dog.wmv')
# 2 获取图像的属性
frame_width=int(cap.get(3))#图像高
frame_height=int(cap.get(4))
# 3 创建保存视频的对象
out=cv2.VideoWriter('out.avi',cv2.VideoWriter_fourcc('M','J','P','G'),10,(frame_width,frame_height))
while(True):
#4 获取视频中的每一帧
ret,frame=cap.read()
if ret==True:
# 5 将视频的每一帧写入到输出文件
out.write(frame)
else:
break
# 6 释放视频对象
cap.release()
out.release()
cv2.destroyAllWindows()
学习目标:
理解meanshift算法原理
知道camshift算法
使用meanshift和camshift进行目标追踪
meanshift算法的原理很简单,假设有一堆点集,还有一个小窗口,这个窗口可能是圆形的,现在要移动这个窗口到点集密度最大的区域中,如下图:
最开始的窗口是蓝色圆环区域,命名为C1,蓝色圆环的圆心用一个蓝色的矩形标注,命名为C1_o。
而窗口中所有点的点集构成的质心在C1_r处,显然圆环的形心和质心并不重合;移动蓝色窗口,使得形心与之前得到的质心重合;在新移动后的圆环的区域中再次寻找圆环当中所包围点集的质心,然后再次移动,通常情况下,形心和质心是不重合的,不断执行上面的移动过程,直到形心和质心大致重合,这样UI后圆形窗口会落到像素分布最大的地方,也就是图中绿色圈,命名为C2。
meanshift算法除了应用在视频追踪中,在聚类、平滑等各种涉及到数据以及非监督学习的场合中均有重要应用,是一个应用广泛的算法。
图像是一个矩阵信息,如何在一个视频当中使用meanshift算法来追踪一个运动的物体呢?,流程如下:
(1)首先在图像中选定一个目标区域
(2)计算选定区域的直方图分布,一般是HSV色彩空间的直方图
(3)对下一帧图像b同样计算直方图分布
(4)计算图像b当中与选定区域直方图分布最为相似的部分进行移动,直到找到最相似的区域,便完成了在图像b中的目标追踪。
(5)重复3到4的过程,就完成了整个视频的目标追踪
在OpenCV中实现Meanshift的API是:
cv2.meanshift(probImage,window,criteria)
参数:
proImage:ROI区域,即目标的直方图的反向投影
window:初始搜寻窗口,就是定义ROI的rectangle
criteria:确定窗口搜索停止的准则,主要有迭代次数达到设置的最大值,窗口中心的漂移值大于某个设定的限值等
实现Meanshift的主要流程是:
(1)读取视频文件:cv2.videoCapture()
(2)感兴趣区域设置:获取第一帧图像,并设置目标区域,既 感兴趣区域
(3)计算直方图:计算感兴趣区域的HSV直方图,并进行归一化
(4)目标追踪:设置窗口搜索停止条件,直方图反向投影,进行目标追踪,并在目标位置绘制矩形框。
import numpy
import cv2
# 1 读取视频
cap=cv2.VideoCapture('Dog.wmv')
# 2 获取第一帧图西乡,并锁定目标位置
ret,frame=cap.read()
## 2.1 目标位置行高列宽
r,h,c,w=197,141,8,208
track_window=(c,r,w,h)
roi=frame[r:r+h,c:c+w]
# 3 计算直方图
## 3.1 转换色彩空间(HSV)
hsv_roi=cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)
## 3.2 计算直方图
hsv_hist=cv2.calcHist([hsv_roi],[0],None,[180],[0,180])
cv2.normalize(hsv_hist,hsv_hist,0,255,cv2.NORM_MINMAX)
# 4 目标追踪
term=(cv2.TermCriteria_EPS|cv2.TERM_CRITERIA_COUNT,10,1)
while (True):
ret,frame=cap.read()
if ret==True:
hst=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
dst=cv2.calcBackProject([hst],[8],hsv_roi,[0,100],1)
ret,win=cv2.meanShift(dst,win,term)
x,y,w,h=win
img2=cv2.rectangle(frame,(x,y),(x+w,y+h),255,2)
cv2.imshow('frame',img2)
if cv2.waitKey(60)&0xFF==ord('q'):
break
# 5 释放资源
cap.release()
cv2.destroyAllWindows()
meanshift算法有一个问题,就是检测的窗口的大小是固定的,而目标近和远大小是变化的,固定的窗口大小是不合适的,所以需要根据目标大小和角度来对窗口的大小和角度进行修正,camshift算法可以帮助解决这个问题。
Camshift算法全称是连续自适应Meanshift算法,是对MeanShift算法的改进算法,可以随着跟踪目标的大小变化实时调整窗口的大小,具有较好的跟踪效果。
Camshift算法首先应用meanshift算法,一旦meanshift算法收敛,它就会更新窗口大小,还计算最佳拟合椭圆的方向,从而根据目标的位置和大小更新搜索窗口,如下图所示:
Camshift算法在OpenCV中实现时,只需将meanshift函数改为camshift函数即可