这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » OpenVINO生态社区 » 【原创】项目实战—人脸检测之级联分类器实战(二)

共11条 1/2 1 2 跳转至

【原创】项目实战—人脸检测之级联分类器实战(二)

高工
2020-08-20 20:03:50     打赏

项目实战—人脸检测之级联分类器实战

在上个教程中,使用 Adaboost 学习分类函数过程非常有效,但仍存在一个重大问题。在图像中,大部分图像为非面部区域。对图像的每个区域给予等同的注意力是没有意义的,因为我们应该主要关注最有可能包含人脸的区域。Viola Jone 使用级联分类器在减少了计算时间的同时,实现了更高的检测率。

关键思想是在识别人脸区域时排除不含人脸的子窗口。由于任务是正确识别人脸,我们希望假阴率最小,即包含人脸却未被识别的子窗口最少。

每个子窗口都使用一系列分类器。这些分类器是简单的决策树:

·           如果第一个分类器检测为正样本,继续用第二个

·           如果第二个分类器检测是正样本,继续用第三个

·           以此类推

虽然有时可能包含人脸的图被认成负样本被子窗口漏检。但初级分类器以较低的计算成本筛除了大多数负样本,下图的分类器可额外消除更多的负样本,但需要更多的计算量。

image.png

使用 Adaboost 训练分类器,并调整阈值使错误率降到最低。在训练该模型时,变量如下:

·             每个阶段分类器数量

·             每个阶段的特征数量

·             每个阶段的阈值

方便的是,在 OpenCV 中,整个模型已经经过预训练,可直接用于人脸检测。

如果想了解有关 Boosting 技术的更多信息,欢迎查看作者关于 Adaboost 的文章:

https://maelfabien.github.io/machinelearning/adaboost

实战

下一步是找到预训练的权重。我们将使用默认的预训练模型来检测人脸、眼睛和嘴巴。

关于OpenCV中的已经训练好的XML文件,这个需要自行去官网下载,这边就不再赘述。

确定路径后,以此方式声明级联分类器:

cascPath = "haarcascade_frontalface_default.xml"
 eyePath = "haarcascade_eye.xml"
 smilePath = "haarcascade_smile.xml"
 faceCascade = cv2.CascadeClassifier(cascPath)
 eyeCascade = cv2.CascadeClassifier(eyePath)
 smileCascade = cv2.CascadeClassifier(smilePath)

检测图像中的人脸

在实现实时人脸检测算法之前,让我们先尝试在图像上简单检测一下。从加载测试图像开始:

gray = cv2.imread('min.jpg',0)
 plt.figure(figsize=(12,8))
 plt.imshow(gray, cmap='gray')
 plt.show()

 

image.png

然后开始检测人脸,并将检测到的人脸框起来。


# Detect faces
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
flags=cv2.CASCADE_SCALE_IMAGE
)
# For each face
for (x, y, w, h) in faces: 
    # Draw rectangle around the face
    cv2.rectangle(gray, (x, y), (x+w, y+h), (255, 255, 255), 3)

以下是 detectMultiScale 函数常见的参数列表:

·           scaleFactor:确定每个图像缩放比例大小。

·           minNeighbors:确定每个候选矩形应保留多少个相邻框。

·           minSize:最小目标的大小。小于该值的目标将被忽略。

·           maxSize:最大目标的大小。大于该值的目标将被忽略。

最后,显示结果:


plt.figure(figsize=(12,8))
plt.imshow(gray, cmap='gray')
plt.show()

image.png

在测试图像上成功检测到人脸。现在开始实时检测!

实时人脸检测

下面继续进行实时人脸检测的 Python 实现。第一步是启动摄像头,并拍摄视频。然后,将图像转换为灰度图。这用于减小输入图像的维数。实际上,我们应用了一个简单的线性变换,而不是每个像素用三个点来描述红、绿、蓝。

image.png

这在 OpenCV 中是默认实现的。


video_capture = cv2.VideoCapture(0)
while True:
    # Capture frame-by-frame
    ret, frame = video_capture.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

现在我们使用上述定义的 faceCascade 变量,它包含一个预训练算法,现在将其用于灰度图。


faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags=cv2.CASCADE_SCALE_IMAGE
        )

对于检测到的每个人脸,都加上一个矩形框:

for (x, y, w, h) in faces:
        if w > 250 :
            cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)
            roi_gray = gray[y:y+h, x:x+w]
            roi_color = frame[y:y+h, x:x+w]

对于检测到的每张嘴,都加上一个矩形框:


smile = smileCascade.detectMultiScale(
        roi_gray,
        scaleFactor= 1.16,
        minNeighbors=35,
        minSize=(25, 25),
        flags=cv2.CASCADE_SCALE_IMAGE
    )
    for (sx, sy, sw, sh) in smile:
        cv2.rectangle(roi_color, (sh, sy), (sx+sw, sy+sh), (255, 0, 0), 2)
        cv2.putText(frame,'Smile',(x + sx,y + sy), 1, 1, (0, 255, 0), 1)

对于检测到的每双眼睛,都加上一个矩形框:


eyes = eyeCascade.detectMultiScale(roi_gray)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
        cv2.putText(frame,'Eye',(x + ex,y + ey), 1, 1, (0, 255, 0), 1)

然后计算人脸总数,显示整体图像:


cv2.putText(frame,'Number of Faces : ' + str(len(faces)),(40, 40), font, 1,(255,0,0),2)      
    # Display the resulting frame
    cv2.imshow('Video', frame)

当按下 q 键时,执行退出选项。


if cv2.waitKey(1) & 0xFF == ord('q'):
        break

最后当所有操作完成后,关闭所有窗口。


video_capture.release()
cv2.destroyAllWindows()

封装代码:

import cv2
 import matplotlib.pyplot as plt
 
 cascPath = "haarcascade_frontalface_default.xml"
 eyePath = "haarcascade_eye.xml"
 smilePath = "haarcascade_smile.xml"
 
 faceCascade = cv2.CascadeClassifier(cascPath)
 eyeCascade = cv2.CascadeClassifier(eyePath)
 smileCascade = cv2.CascadeClassifier(smilePath)
 
 font = cv2.FONT_HERSHEY_SIMPLEX
 video_capture = cv2.VideoCapture(0)
 
 
 while True:
     # Capture frame-by-frame
     ret, frame = video_capture.read()
 
     gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
 
     faces = faceCascade.detectMultiScale(
         gray,
         scaleFactor=1.1,
         minNeighbors=5,
         minSize=(200, 200),
         flags=cv2.CASCADE_SCALE_IMAGE
     )
 
     # Draw a rectangle around the faces
     for (x, y, w, h) in faces:
         cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 3)
         roi_gray = gray[y:y + h, x:x + w]
         roi_color = frame[y:y + h, x:x + w]
         cv2.putText(frame, 'Face', (x, y), font, 2, (255, 0, 0), 5)
         smile = smileCascade.detectMultiScale(
             roi_gray,
             scaleFactor=1.16,
             minNeighbors=35,
             minSize=(25, 25),
             flags=cv2.CASCADE_SCALE_IMAGE
         )
 
         for (sx, sy, sw, sh) in smile:
             cv2.rectangle(roi_color, (sh, sy), (sx + sw, sy + sh), (255, 0, 0), 2)
             cv2.putText(frame, 'Smile', (x + sx, y + sy), 1, 1, (0, 255, 0), 1)
 
         eyes = eyeCascade.detectMultiScale(roi_gray)
         for (ex, ey, ew, eh) in eyes:
             cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
             cv2.putText(frame, 'Eye', (x + ex, y + ey), 1, 1, (0, 255, 0), 1)
 
     cv2.putText(frame, 'Number of Faces : ' + str(len(faces)), (40, 40), font, 1, (255, 0, 0), 2)
     # Display the resulting frame
     cv2.imshow('Video', frame)
 
     if cv2.waitKey(1) & 0xFF == ord('q'):
         break
 
 # When everything is done, release the capture
 video_capture.release()
 cv2.destroyAllWindows()

至于结果大家自行实验。用自己的摄像头就可以。

 

 


对计算机视觉感兴趣?这个社区推荐给你~

>>点击了解OpenVINO生态开发社区



高工
2020-08-21 22:30:01     打赏
2楼

继续更新


工程师
2020-08-22 15:05:24     打赏
3楼

实战经验还是比较重要的


工程师
2020-08-23 16:57:15     打赏
4楼

学习一下


工程师
2020-08-23 17:02:35     打赏
5楼

干货


工程师
2020-08-23 17:07:23     打赏
6楼

果断收藏


工程师
2020-08-23 17:13:02     打赏
7楼

学习到了


工程师
2020-08-23 17:18:46     打赏
8楼

感谢楼主分享


工程师
2020-08-23 17:23:40     打赏
9楼

谢谢分享


工程师
2020-08-23 20:04:35     打赏
10楼

讲解的非常不错


共11条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]