摄像头采集
# 使用照相机
# 参数为电脑的摄像头,0为第一个,1为第二个,以此类推
capture = cv2.VideoCapture(0)
# 使用cv2.VideoWriter_fourcc()确定编/解码的类型
fourcc = cv2.VideoWriter_fourcc(*'XVID')
'''
1.设置要保存的具体文件名;
2.编/解码的类型
3.视频的帧速率
4.视频的长度和宽度
'''
out=cv2.VideoWriter('test.avi',fourcc, 20, (640,480))
# 使用照相机,等待1ms,若有按键按下,则退出循环,否则再次进入循环
while True:
# frame 是返回的捕获到的帧,如果没有帧被捕获,则该值为空
# retval 表示捕获是否成功,如果成功则该值为 True,不成功则为 False
retval, frame = capture.read()
cv2.imshow("camera", frame)
key = cv2.waitKey(1)
if key != -1:
break
else:
out.write(frame)
# 释放写对象
out.release()
# 释放摄像头对象
capture.release()
# 关闭所有已打开的窗口
cv2.destroyAllWindows()
视频处理
边缘检测示例代码:
# 提取摄像头
cap = cv2.VideoCapture('test.avi')
# 使用cv2.VideoWriter_fourcc()确定编/解码的类型
'''
VideoWriter_fourcc()常见的编码参数
cv2.VideoWriter_fourcc('M', 'P', '4', 'V') # MPEG-4编码 .mp4 可指定结果视频的大小
cv2.VideoWriter_fourcc('X','2','6','4') # MPEG-4编码 .mp4 可指定结果视频的大小
cv2.VideoWriter_fourcc('I', '4', '2', '0') # 该参数是YUV编码类型,文件名后缀为.avi 广泛兼容,但会产生大文件
cv2.VideoWriter_fourcc('P', 'I', 'M', 'I') # 该参数是MPEG-1编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc('X', 'V', 'I', 'D') # 该参数是MPEG-4编码类型,文件名后缀为.avi,可指定结果视频的大小
cv2.VideoWriter_fourcc('T', 'H', 'E', 'O') # 该参数是Ogg Vorbis,文件名后缀为.ogv
cv2.VideoWriter_fourcc('F', 'L', 'V', '1') # 该参数是Flash视频,文件名后缀为.flv
'''
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# 获取读入视频的宽和高
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
'''
1.设置要保存的具体文件名;
2.编/解码的类型
3.视频的帧速率
4.视频的长度和宽度
5.彩色(true)还是灰色(false)
'''
out=cv2.VideoWriter('test_边缘检测.avi',fourcc, 20, (width, height),False)
while(cap.isOpened()):
ret, frame = cap.read()
if frame is None:
break
else:
cv2.imshow('frame', frame)
# 边缘检测
img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
img_canny = cv2.Canny(img_gray, 100, 200)
cv2.imshow('img_canny', img_canny)
out.write(img_canny)
key = cv2.waitKey(5)
if key != -1:
break
cap.release()
cv2.destroyAllWindows()
角点检测示例代码:
def corner(img):
# 先转成灰度图
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 提取特征
# 500为角点数目最大值;0.1为角点的品质因子;10为两个角点之间最短欧式距离
corners = cv2.goodFeaturesToTrack(img_gray, 500, 0.1, 10)
# 处理角点,使用红色实心圆(像素厚度为-1)标记
for corner in corners:
x, y = corner.ravel()
cv2.circle(img, (int(x), int(y)), 3, (255, 0, 255), -1)
return img
# 提取摄像头
cap = cv2.VideoCapture('test.mp4')
# 使用cv2.VideoWriter_fourcc()确定编/解码的类型
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
# 获取读入视频的宽和高
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
out=cv2.VideoWriter('test_角点检测.mp4',fourcc, 20, (width, height))
# 读取视频并处理
while(cap.isOpened()):
ret, frame = cap.read()
if frame is None:
break
else:
cv2.imshow('frame', frame)
img_corners=corner(frame)
cv2.imshow('img_corners', img_corners)
out.write(img_corners)
key = cv2.waitKey(1)
if key != -1:
break
cap.release()
cv2.destroyAllWindows()
帧差法检测运动目标
帧差法:对视频图像序列中相邻两帧作差分运算,获得运动目标轮廓。
当视频中出现移动的物体时,帧与帧之间会出现差别,两帧相减,得到两帧图像亮度差的绝对值,判断其是否大于阈值来确定视频中有无物体运动。
帧差法简单、容易实现、时间复杂度较低且对快速移动的目标很敏感,但容易受到光照变化和背景的干扰。
cap = cv2.VideoCapture('test.avi')
# 创建一个椭圆形结构的核
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 4))
background = None
while True:
_, frame = cap.read()
if frame is None:
break
# 对帧进行预处理,先转灰度图,再进行高斯滤波
# 用高斯滤波进行模糊处理,因为视频会因自然震动、光照变化或者摄像头本身等原因而产生噪声
img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
img_gs = cv2.GaussianBlur(img_gray, (21, 21), 0)
# 将第一帧设置为整个输入的背景
if background is None:
background = img_gs
continue
# 将两幅图像作差,获取差分图,返回与输入数组相同大小和类型的输出数组
img_diff = cv2.absdiff(background, img_gs)
# 二值化
_,img_thre = cv2.threshold(img_diff, 70, 255, cv2.THRESH_BINARY)
img_erod = cv2.erode(img_thre, kernel, iterations=1)
# 膨胀,对孔和缺陷进行处理
img_dila = cv2.dilate(img_erod, kernel, iterations=1)
# 查找图像轮廓
'''
返回值:
contours:返回的轮廓信息,每个轮廓都是由若干个点所构成的。
hierarchy:图像的拓扑信息(轮廓层次)。图像内的轮廓可能位于不同的位置。
比如,一个轮廓在另一个轮廓的内部。在这种情况下,我们将外部的轮廓称为父轮廓,内部的轮廓称为子轮廓。按照上述关系分类,一幅图像中所有轮廓之间就建立了父子关系。
根据轮廓之间的关系,就能够确定一个轮廓与其他轮廓是如何连接的。
比如,确定一个轮廓是某个轮廓的子轮廓,或者是某个轮廓的父轮廓。上述关系被称为层次(组织结构),返回值 hierarchy 就包含上述层次关系。
每个轮廓 contours[i]对应 4 个元素来说明当前轮廓的层次关系。其形式为:[Next,Previous,First_Child,Parent]
Next:后一个轮廓的索引编号。
Previous:前一个轮廓的索引编号。
First_Child:第 1 个子轮廓的索引编号。
Parent:父轮廓的索引编号。
参数:
image:8位单通道二值图像。
mode:轮廓检索模式。
cv2.RETR_EXTERNAL:只检测外轮廓。
cv2.RETR_LIST:对检测到的轮廓不建立等级关系。
cv2.RETR_CCOMP:检索所有轮廓并将它们组织成两级层次结构。
上面的一层为外边界,下面的一层为内孔的边界。如果内孔内还有一个连通物体,那么这个物体的边界仍然位于顶层。
cv2.RETR_TREE:建立一个等级树结构的轮廓。
method:轮廓的近似方法,决定了如何表达轮廓,可以为如下值:
cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,相邻两个点的像素位置差不超过 1,即 max(abs(x1-x2),abs(y2-y1))=1。
cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标。例如,在极端的情况下,一个矩形只需要用 4 个点来保存轮廓信息。
cv2.CHAIN_APPROX_TC89_L1:使用 teh-Chinl chain 近似算法的一种风格。
cv2.CHAIN_APPROX_TC89_KCOS:使用 teh-Chinl chain 近似算法的一种风格。
'''
contours, hierarchy = cv2.findContours(img_dila.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# cv2.contourArea()计算轮廓内面积。对于矩形区域,只显示大于给定阈值的轮廓,一些微小的变化也就不会显示。对于光照不变和噪声低的摄像头可不设定轮廓最小尺寸的阈值
if cv2.contourArea(contour) > 360:
# 返回包围轮廓的矩形的边界信息(左上角顶点坐标值及矩形宽和高)
(x, y, w, h) = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0,0,255), 2)
cap.release()
cv2.destroyAllWindows()