最后一天啦。虽然我自己写不出来,但是对于OpenCV处理图像有了感觉不错的了解,而且通过课程把代码都跑起来了,现在的想法是需要了就去翻,哈哈哈,还是太菜。
1 Fast算法
1.1 原理
前面介绍过几个特征检测器,它们的效果都很好,特别是SIFT和SURF算法,但是从实时处理的角度来看,效率还是太低了。为了解决这个问题,Edward Rosten和Tom Drummond在2006年提出了FAST算法,并在2010年对其进行了修正。
FAST (全称Features from accelerated segment test)是一种用于角点检测的算法,该算法的原理是取图像中检测点,以该点为圆心的周围邻域内像素点判断检测点是否为角点,通俗的讲就是若一个像素周围有一定数量的像素与该点像素值不同,则认为其为角点。
1.1.1 FAST算法的基本流程
- 在图像中选取一个像素点 p,来判断它是不是关键点。$$I_p$$等于像素点 p的灰度值。
- 以r为半径画圆,覆盖p点周围的M个像素,通常情狂下,设置 r=3,则 M=16
- 设置一个阈值t,如果在这 16 个像素点中存在 n 个连续像素点的灰度值都高于$$I_p+t$$,或者低于$$I_p - t$$,那么像素点 p 就被认为是一个角点。n 一般取值为 12。
- 由于在检测特征点时是需要对图像中所有的像素点进行检测,然而图像中的绝大多数点都不是特征点,如果对每个像素点都进行上述的检测过程,那显然会浪费许多时间,因此采用一种进行非特征点判别的方法:首先对候选点的周围每个 90 度的点:1,9,5,13 进行测试(先测试 1 和 9, 如果它们符合阈值要求再测试 5 和 13)。如果 p 是角点,那么这四个点中至少有 3 个要符合阈值要求,否则直接剔除。对保留下来的点再继续进行测试(是否有 12 的点符合阈值要求)。
虽然这个检测器的效率很高,但它有以下几条缺点:
- 获得的候选点比较多
- 特征点的选取不是最优的,因为它的效果取决与要解决的问题和角点的分布情况。
- 进行非特征点判别时大量的点被丢弃
- 检测到的很多特征点都是相邻的
前 3 个问题可以通过机器学习的方法解决,最后一个问题可以使用非最大值抑制的方法解决。
1.1.2机器学习的角点检测器
- 选择一组训练图片(最好是跟最后应用相关的图片)
- 使用 FAST 算法找出每幅图像的特征点,对图像中的每一个特征点,将其周围的 16 个像素存储构成一个向量P。
- 每一个特征点的 16 像素点都属于三类中的一种
- 根据这些像素点的分类,特征向量 P 也被分为 3 个子集:Pd ,Ps ,Pb,
- 定义一个新的布尔变量$$K_p$$,如果 p 是角点就设置为 Ture,如果不是就设置为 False。
- 利用特征值向量p,目标值是$K_p$,训练ID3 树(决策树分类器)。
- 将构建好的决策树运用于其他图像的快速的检测。
1.1.3 非极大值抑制
在筛选出来的候选角点中有很多是紧挨在一起的,需要通过非极大值抑制来消除这种影响。
为所有的候选角点都确定一个打分函数$$V $$ , $$V $$的值可这样计算:先分别计算$$I_p$$与圆上16个点的像素值差值,取绝对值,再将这16个绝对值相加,就得到了$$V $$的值
最后比较毗邻候选角点的 V 值,把V值较小的候选角点pass掉。
FAST算法的思想与我们对角点的直观认识非常接近,化繁为简。FAST算法比其它角点的检测算法快,但是在噪声较高时不够稳定,这需要设置合适的阈值。
1.2 实现
OpenCV中的FAST检测算法是用传统方法实现的,
1.实例化fast
fast = =cv.FastFeatureDetector_create( threshold, nonmaxSuppression)
参数:
- threshold:阈值t,有默认值10
- nonmaxSuppression:是否进行非极大值抑制,默认值True
返回:
- Fast:创建的FastFeatureDetector对象
2.利用fast.detect检测关键点,没有对应的关键点描述
kp = fast.detect(grayImg, None)
参数:
- gray: 进行关键点检测的图像,注意是灰度图像
返回:
- kp: 关键点信息,包括位置,尺度,方向信息
3.将关键点检测结果绘制在图像上,与在sift中是一样的
cv.drawKeypoints(image, keypoints, outputimage, color, flags)
示例:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 1 读取图像
img = cv.imread('./image/tv.jpg')
# 2 Fast角点检测
# 2.1 创建一个Fast对象,传入阈值,注意:可以处理彩色空间图像
fast = cv.FastFeatureDetector_create(threshold=30)
# 2.2 检测图像上的关键点
kp = fast.detect(img,None)
# 2.3 在图像上绘制关键点
img2 = cv.drawKeypoints(img, kp, None, color=(0,0,255))
# 2.4 输出默认参数
print( "Threshold: {}".format(fast.getThreshold()) )
print( "nonmaxSuppression:{}".format(fast.getNonmaxSuppression()) )
print( "neighborhood: {}".format(fast.getType()) )
print( "Total Keypoints with nonmaxSuppression: {}".format(len(kp)) )
# 2.5 关闭非极大值抑制
fast.setNonmaxSuppression(0)
kp = fast.detect(img,None)
print( "Total Keypoints without nonmaxSuppression: {}".format(len(kp)) )
# 2.6 绘制为进行非极大值抑制的结果
img3 = cv.drawKeypoints(img, kp, None, color=(0,0,255))
# 3 绘制图像
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img2[:,:,::-1])
axes[0].set_title("加入非极大值抑制")
axes[1].imshow(img3[:,:,::-1])
axes[1].set_title("未加入非极大值抑制")
plt.show()
2 ORB 算法
2.1 原理
SIFT和SURF算法是受专利保护的,在使用他们时我们是要付费的,但是ORB(Oriented Fast and Rotated Brief)不需要,它可以用来对图像中的关键点快速创建特征向量,并用这些特征向量来识别图像中的对象。
2.1.1 ORB算法流程
ORB算法结合了Fast和Brief算法,提出了构造金字塔,为Fast特征点添加了方向,从而使得关键点具有了尺度不变性和旋转不变性。具体流程描述如下:
- 构造尺度金字塔,金字塔共有n层,与SIFT不同的是,每一层仅有一幅图像。第s层的尺度为:
$$\sigma_0$$是初始尺度,默认为1.2,原图在第0层。
- 在不同的尺度上利用Fast算法检测特征点,采用Harris角点响应函数,根据角点的响应值排序,选取前N个特征点,作为本尺度的特征点。
- 计算特征点的主方向,计算以特征点为圆心半径为r的圆形邻域内的灰度质心位置,将从特征点位置到质心位置的方向做特征点的主方向。
- 为了解决旋转不变性,将特征点的邻域旋转到主方向上利用Brief算法构建特征描述符,至此就得到了ORB的特征描述向量。
2.1.2 BRIEF算法
BRIEF是一种特征描述子提取算法,并非特征点的提取算法,一种生成二值化描述子的算法,不提取代价低,匹配只需要使用简单的汉明距离(Hamming Distance)利用比特之间的异或操作就可以完成。因此,时间代价低,空间代价低,效果还挺好是最大的优点。
算法的步骤介绍如下:
- 图像滤波:原始图像中存在噪声时,会对结果产生影响,所以需要对图像进行滤波,去除部分噪声。
- 选取点对:以特征点为中心,取S*S的邻域窗口,在窗口内随机选取N组点对,一般N=128,256,512,默认是256,关于如何选取随机点对,提供了五种形式,结果如下图所示:
- x,y方向平均分布采样
- x,y均服从Gauss(0,S^2/25)各向同性采样
- x服从Gauss(0,S^2/25),y服从Gauss(0,S^2/100)采样
- x,y从网格中随机获取
- x一直在(0,0),y从网格中随机选取
图中一条线段的两个端点就是一组点对,其中第二种方法的结果比较好。
- 建描述符:假设x,y是某个点对的两个端点,p(x),p(y)是两点对应的像素值
对每一个点对都进行上述的二进制赋值,形成BRIEF的关键点的描述特征向量,该向量一般为 128-512 位的字符串,其中仅包含 1 和 0
2.2 实现
在OPenCV中实现ORB算法,使用的是:
1.实例化ORB
orb = cv.xfeatures2d.orb_create(nfeatures)
参数:
- nfeatures: 特征点的最大数量
2.利用orb.detectAndCompute()检测关键点并计算
kp,des = orb.detectAndCompute(gray,None)
参数:
- gray: 进行关键点检测的图像,注意是灰度图像
返回:
- kp: 关键点信息,包括位置,尺度,方向信息
- des: 关键点描述符,每个关键点BRIEF特征向量,二进制字符串,
3.将关键点检测结果绘制在图像上
cv.drawKeypoints(image, keypoints, outputimage, color, flags)
示例:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 1 图像读取
img = cv.imread('./image/tv.jpg')
# 2 ORB角点检测
# 2.1 实例化ORB对象
orb = cv.ORB_create(nfeatures=500)
# 2.2 检测关键点,并计算特征描述符
kp,des = orb.detectAndCompute(img,None)
print(des.shape)
# 3 将关键点绘制在图像上
img2 = cv.drawKeypoints(img, kp, None, color=(0,0,255), flags=0)
# 4. 绘制图像
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img2[:,:,::-1])
plt.xticks([]), plt.yticks([])
plt.show()
视频读写
1 从文件中读取视频并播放
在OpenCV中我们要获取一个视频,需要创建一个VideoCapture对象,指定你要读取的视频文件:
- 创建读取视频的对象
cap = cv.VideoCapture(filepath)
参数:
-
- filepath: 视频文件路径
- 视频的属性信息
2.1. 获取视频的某些属性,
retval = cap.get(propId)
参数:
-
- propId: 从0到18的数字,每个数字表示视频的属性
- 2.2 修改视频的属性信息
- cap.set(propId,value)
参数:
-
- proid: 属性的索引,与上面的表格相对应
- value: 修改后的属性值
- 判断图像是否读取成功
- isornot = cap.isOpened()
- 若读取成功则返回true,否则返回False
- 获取视频的一帧图像
- ret, frame = cap.read()
参数:
-
- ret: 若获取成功返回True,获取失败,返回False
- Frame: 获取到的某一帧的图像
- 调用cv.imshow()显示图像,在显示图像时使用cv.waitkey()设置适当的持续时间,如果太低视频会播放的非常快,如果太高就会播放的非常慢,通常情况下我们设置25ms就可以了。
- 最后,调用cap.realease()将视频释放掉
import numpy as np
import cv2 as cv
# 1.获取视频对象
cap = cv.VideoCapture('DOG.wmv')
# 2.判断是否读取成功
while(cap.isOpened()):
# 3.获取每一帧图像
ret, frame = cap.read()
# 4. 获取成功显示图像
if ret == True:
cv.imshow('frame',frame)
# 5.每一帧间隔为25ms
if cv.waitKey(25) & 0xFF == ord('q'):
break
# 6.释放视频对象
cap.release()
cv.destoryAllwindows()
2 保存视频
在OpenCV中我们保存视频使用的是VedioWriter对象,在其中指定输出文件的名称,如下所示:
- 创建视频写入的对象
out = cv2.VideoWriter(filename,fourcc, fps, frameSize)
参数:
- filename:视频保存的位置
- fourcc:指定视频编解码器的4字节代码
- fps:帧率
- frameSize:帧大小
- 设置视频的编解码器,如下所示,
retval = cv2.VideoWriter_fourcc( c1, c2, c3, c4 )
参数:
-
- c1,c2,c3,c4: 是视频编解码器的4字节代码,在fourcc.org中找到可用代码列表,与平台紧密相关,常用的有:
在Windows中:DIVX(.avi)
在OS中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。
- 利用cap.read()获取视频中的每一帧图像,并使用out.write()将某一帧图像写入视频中。
- 使用cap.release()和out.release()释放资源。
import cv2 as cv
import numpy as np
# 1. 读取视频
cap = cv.VideoCapture("DOG.wmv")
# 2. 获取图像的属性(宽和高,),并将其转换为整数
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
# 3. 创建保存视频的对象,设置编码格式,帧率,图像的宽高等
out = cv.VideoWriter('outpy.avi',cv.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()
cv.destroyAllWindows()
视频追踪
1.meanshift
1.1原理
meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。
最开始的窗口是蓝色圆环的区域,命名为C1。蓝色圆环的圆心用一个蓝色的矩形标注,命名为C1_o。
而窗口中所有点的点集构成的质心在蓝色圆形点C1_r处,显然圆环的形心和质心并不重合。所以,移动蓝色的窗口,使得形心与之前得到的质心重合。在新移动后的圆环的区域当中再次寻找圆环当中所包围点集的质心,然后再次移动,通常情况下,形心和质心是不重合的。不断执行上面的移动过程,直到形心和质心大致重合结束。 这样,最后圆形的窗口会落到像素分布最大的地方,也就是图中的绿色圈,命名为C2。
meanshift算法除了应用在视频追踪当中,在聚类,平滑等等各种涉及到数据以及非监督学习的场合当中均有重要应用,是一个应用广泛的算法。
图像是一个矩阵信息,如何在一个视频当中使用meanshift算法来追踪一个运动的物体呢? 大致流程如下:
- 首先在图像上选定一个目标区域
- 计算选定区域的直方图分布,一般是HSV色彩空间的直方图。
- 对下一帧图像b同样计算直方图分布。
- 计算图像b当中与选定区域直方图分布最为相似的区域,使用meanshift算法将选定区域沿着最为相似的部分进行移动,直到找到最相似的区域,便完成了在图像b中的目标追踪。
- 重复3到4的过程,就完成整个视频目标追踪。
通常情况下我们使用直方图反向投影得到的图像和第一帧目标对象的起始位置,当目标对象的移动会反映到直方图反向投影图中,meanshift 算法就把我们的窗口移动到反向投影图像中灰度密度最大的区域了。如下图所示:
直方图反向投影的流程是:
假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
- 从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
- 生成临时图像的直方图;
- 用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
- 直方图对比结果c,就是结果图像(0,0)处的像素值;
- 切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
- 重复1~5步直到输入图像的右下角,就形成了直方图的反向投影。
1.2 实现
在OpenCV中实现Meanshift的API是:
cv.meanShift(probImage, window, criteria)
参数:
- probImage: ROI区域,即目标的直方图的反向投影
- window: 初始搜索窗口,就是定义ROI的rect
- criteria: 确定窗口搜索停止的准则,主要有迭代次数达到设置的最大值,窗口中心的漂移值大于某个设定的限值等。
实现Meanshift的主要流程是:
- 读取视频文件:cv.videoCapture()
- 感兴趣区域设置:获取第一帧图像,并设置目标区域,即感兴趣区域
- 计算直方图:计算感兴趣区域的HSV直方图,并进行归一化
- 目标追踪:设置窗口搜索停止条件,直方图反向投影,进行目标追踪,并在目标位置绘制矩形框。
示例:
import numpy as np
import cv2 as cv
# 1.获取图像
cap = cv.VideoCapture('DOG.wmv')
# 2.获取第一帧图像,并指定目标位置
ret,frame = cap.read()
# 2.1 目标位置(行,高,列,宽)
r,h,c,w = 197,141,0,208
track_window = (c,r,w,h)
# 2.2 指定目标的感兴趣区域
roi = frame[r:r+h, c:c+w]
# 3. 计算直方图
# 3.1 转换色彩空间(HSV)
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
# 3.2 去除低亮度的值
# mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
# 3.3 计算直方图
roi_hist = cv.calcHist([hsv_roi],[0],None,[180],[0,180])
# 3.4 归一化
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# 4. 目标追踪
# 4.1 设置窗口搜索终止条件:最大迭代次数,窗口中心漂移最小值
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
while(True):
# 4.2 获取每一帧图像
ret ,frame = cap.read()
if ret == True:
# 4.3 计算直方图的反向投影
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)
# 4.4 进行meanshift追踪
ret, track_window = cv.meanShift(dst, track_window, term_crit)
# 4.5 将追踪的位置绘制在视频上,并进行显示
x,y,w,h = track_window
img2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
cv.imshow('frame',img2)
if cv.waitKey(60) & 0xFF == ord('q'):
break
else:
break
# 5. 资源释放
cap.release()
cv.destroyAllWindows()
2 Camshift
大家认真看下上面的结果,有一个问题,就是检测的窗口的大小是固定的,而狗狗由近及远是一个逐渐变小的过程,固定的窗口是不合适的。所以我们需要根据目标的大小和角度来对窗口的大小和角度进行修正。CamShift可以帮我们解决这个问题。
CamShift算法全称是“Continuously Adaptive Mean-Shift”(连续自适应MeanShift算法),是对MeanShift算法的改进算法,可随着跟踪目标的大小变化实时调整搜索窗口的大小,具有较好的跟踪效果。
Camshift算法首先应用meanshift,一旦meanshift收敛,它就会更新窗口的大小,还计算最佳拟合椭圆的方向,从而根据目标的位置和大小更新搜索窗口。如下图所示:
Camshift在OpenCV中实现时,只需将上述的meanshift函数改为Camshift函数即可:
将Camshift中的:
import numpy as np
import cv2 as cv
# 1 获取视频
cap = cv.VideoCapture('image/DOG.wmv')
# 2 指定追踪目标
ret,frame = cap.read()
r,h,c,w=197,141,0,208
win = (c,r,w,h)
roi = frame[r:r+h,c:c+w]
# 3 计算直方图
hsv_roi = cv.cvtColor(roi,cv.COLOR_BGR2HSV)
roi_hist = cv.calcHist([hsv_roi],[0],None,[180],[0,180])
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# 4 目标追踪
term = (cv.TERM_CRITERIA_EPS|cv.TERM_CRITERIA_COUNT,10,1)
while(True):
ret,frame = cap.read()
if ret ==True:
hst = cv.cvtColor(frame,cv.COLOR_BGR2HSV)
dst = cv.calcBackProject([hst],[0],roi_hist,[0,180],1)
# 进行meanshift追踪
# ret,win = cv.meanShift(dst,win,term)
#
# x,y,w,h = win
# img2 = cv.rectangle(frame,(x,y),(x+w,y+h),255,2) #绘制矩形
# 进行camshift追踪
# ret,win = cv.CamShift(dst,win,term)
#
# pts = cv.boxPoints(ret)
# pts = np.int0(pts)
# img2 = cv.polylines(frame,[pts],True,255,2)
cv.imshow("frame",img2)
if cv.waitKey(60)&0xFF ==ord('q'):
break
# 5 释放资源
cap.release()
cv.destroyAllWindows()
3 算法总结
Meanshift和camshift算法都各有优势,自然也有劣势:
- Meanshift算法:简单,迭代次数少,但无法解决目标的遮挡问题并且不能适应运动目标的的形状和大小变化。
- camshift算法:可适应运动目标的大小形状的改变,具有较好的跟踪效果,但当背景色和目标颜色接近时,容易使目标的区域变大,最终有可能导致目标跟踪丢失。
案例:人脸案例
1 基础
我们使用机器学习的方法完成人脸检测,首先需要大量的正样本图像(面部图像)和负样本图像(不含面部的图像)来训练分类器。我们需要从其中提取特征。下图中的 Haar 特征会被使用,就像我们的卷积核,每一个特征是一 个值,这个值等于黑色矩形中的像素值之后减去白色矩形中的像素值之和。
Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。
Haar特征可用于于图像任意位置,大小也可以任意改变,所以矩形特征值是矩形模版类别、矩形位置和矩形大小这三个因素的函数。故类别、大小和位置的变化,使得很小的检测窗口含有非常多的矩形特征
得到图像的特征后,训练一个决策树构建的adaboost级联决策器来识别是否为人脸。
2.实现
OpenCV中自带已训练好的检测器,包括面部,眼睛,猫脸等,都保存在XML文件中,我们可以通过以下程序找到他们:
import cv2 as cv print(cv.__file__)
那我们就利用这些文件来识别人脸,眼睛等。检测流程如下:
- 读取图片,并转换成灰度图
- 实例化人脸和眼睛检测的分类器对象
- # 实例化级联分类器
- classifier =cv.CascadeClassifier( "haarcascade_frontalface_default.xml" )
- # 加载分类器
classifier.load('haarcascade_frontalface_default.xml')
- 进行人脸和眼睛的检测
- rect = classifier.detectMultiScale(gray, scaleFactor, minNeighbors, minSize,maxsize)
参数:
-
- Gray: 要进行检测的人脸图像
- scaleFactor: 前后两次扫描中,搜索窗口的比例系数
- minneighbors:目标至少被检测到minNeighbors次才会被认为是目标
- minsize和maxsize: 目标的最小尺寸和最大尺寸
- 将检测结果绘制出来就可以了。
主程序如下所示:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread("D:\Python\Opencvlearn\\02.code\image\yangzi.jpg")
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 2.实例化OpenCV人脸和眼睛识别的分类器
face_cas = cv.CascadeClassifier( "haarcascade_frontalface_default.xml" )
face_cas.load('haarcascade_frontalface_default.xml')
eyes_cas = cv.CascadeClassifier("haarcascade_eye.xml")
eyes_cas.load("haarcascade_eye.xml")
# 3.调用识别人脸
faceRects = face_cas.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
for faceRect in faceRects:
x, y, w, h = faceRect
# 框出人脸
cv.rectangle(img, (x, y), (x + h, y + w),(0,255,0), 3)
# 4.在识别出的人脸中进行眼睛的检测
roi_color = img[y:y+h, x:x+w]
roi_gray = gray[y:y+h, x:x+w]
eyes = eyes_cas.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
# 5. 检测结果的绘制
plt.figure(figsize=(8,6),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('检测结果')
plt.xticks([]), plt.yticks([])
plt.show()
结果:
我们也可在视频中对人脸进行检测:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
cap = cv.VideoCapture("E:\pr\热血高校\\3.mp4")
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# 3.实例化OpenCV人脸识别的分类器
face_cas = cv.CascadeClassifier( "haarcascade_frontalface_default.xml" )
face_cas.load('haarcascade_frontalface_default.xml')
# 4.调用识别人脸
faceRects = face_cas.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
for faceRect in faceRects:
x, y, w, h = faceRect
# 框出人脸
cv.rectangle(frame, (x, y), (x + h, y + w),(0,255,0), 3)
cv.imshow("frame",frame)
if cv.waitKey(1) & 0xFF == ord('q'):
break
# 5. 释放资源
cap.release()
cv.destroyAllWindows()