用 OpenCV 检测猫脸

2022-10-13 13:42 87 阅读 ID:408
磐创AI
磐创AI

Python中的OpenCV猫脸检测代码

使用 OpenCV 的预训练级联分类器可以轻松检测照片或视频中的猫脸。完成所有工作的代码:

import cv2

cascade = cv2.CascadeClassifier('haarcascade_frontalcatface.xml') 
  
cap = cv2.VideoCapture(0) 
  
while True: 
    ret, img = cap.read() 
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
    faces = cascade.detectMultiScale(img_gray, 1.5, 5) 
  
    for (x,y,w,h) in faces: 
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2) 
        roi_gray = img_gray[y:y+h, x:x+w] 
        roi_color = img[y:y+h, x:x+w] 
        
    cv2.imshow('img',img) 

    k = cv2.waitKey(30) & 0xff
    if k == 27: 
        break
  
cap.release() 
  
cv2.destroyAllWindows() 

让我们逐行检查:

  • cv2 库被导入。

如果你还没有安装cv2:

#install cv2
pip install opencv-python
#1
import cv2
  • 加载级联分类器 XML 文件。

OpenCV 目录中有许多预训练的级联。猫也有一个(实际上是两个)。你可以从此地址下载文件:https://github.com/opencv/opencv/tree/4.x/data/haarcascades

#3
cascade = cv2.CascadeClassifier('haarcascade_frontalcatface.xml')

级联分类器

级联是一种集成学习方法,是一种使用多个分类器来提高准确率的方法。第一个级联分类器是 Viola 和 Jones (2001) (https://www.cs.cmu.edu/~efros/courses/LBMV07/Papers/viola-cvpr-01.pdf)的脸部检测器。这个分类器的要求是快速,以便在低功耗 CPU 上实现,例如相机和电话。

级联是一种训练分类器的方法(分类器是一种机器学习算法,可用于标记事物),以便它们在链中协同工作。链中的第一个分类器训练在几百张你试图检测的事物的“正面”图像上,以及一堆不包含该事物的“负面”图像上。

然后,可以将该分类器应用于图像的一个区域,并尝试检测该对象。如果它没有找到它,它将移动到下一个区域,依此类推,直到它找到了东西或搜索了整个图像。这个过程最常用于面部检测和识别。

该算法通过扫描图像并寻找与训练数据中的特征相匹配的 Haar 特征来工作。如果找到匹配项,则将该区域标记为脸。如果未找到匹配项,则将该区域标记为不是脸。

在整个图像中进行这种搜索是一项非常昂贵的业务。想想看,即使是 24x24 的图像也有 160000 个特征。因此,它使用积分图像,这是克服这一问题的有效方法。

积分图像允许快速计算给定矩形下的像素总和,用于计算各种特征。这种方法比传统方法快得多,因此非常适合用于大图像。

位置1的值是A中像素的总和。位置2的值是A和B的总和。位置3:A+C。位置 4 A+B+C+D。D 的值为 (4+1) - (2+3)。

在我们得到这些特征(会有很多)之后,我们需要对它们进行某种过滤,我们需要找出那些能够告诉我们一些东西的特征。Adaboost 是一种机器学习算法,有助于从大量特征中选择最佳特征。它通过关注与手头任务最相关的特征来做到这一点。

我们将每个特征应用于训练图像并获得正负示例中提供的最佳阈值。选择在两个方向上具有最低错误率的特征。Adaboost 的基础分类器很弱。但是当同时使用许多基础分类器时,Adaboost 可以达到一个强大的水平。通过将特征从 160000 个减少到 6000 个特征,实现了超级增益。

通常,包含脸部的区域与整个图像区域相比非常小。因此,到处寻找脸部仍然是低效的。相反,在你的脸更有可能出现在照片中间的区域。

Cascade of Classifiers 是一个引入的概念,以便更有效地将所有特征应用于窗口。这些特征被分组到分类器的不同阶段并被一一应用。如果窗口在第一阶段失败,则不考虑剩余的特征。如果通过,则应用第二阶段的特征并继续该过程。通过所有阶段的窗口就是脸部区域。

  • 为了访问和读取从网络摄像头接收到的数据,我们创建了一个视频捕获对象并传递我们的设备编号。VideoCapture 类用于捕获视频。你可以传递视频文件的路径。
#5
cap = cv2.VideoCapture(0)

启动循环以确保视频数据的连续流。

#7
while True:

VideoCapture 对象(cap)读取并解码,返回下一帧视频。

#8
ret, img = cap.read()
#ret is True if there is a video data
#img is the image

我们将接收到的图像转换为灰度以最小化计算成本。

#9
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  • 现在,是时候在提供的图像帧中检测脸部了。我们将使用我们的级联方法。

detectMultiScale方法检测给定图像中各种大小的对象。它接受灰度图像、scaleFactor、minNeighbors、minSize、maxSize。

scaleFactor用于创建比例金字塔,它是一系列不同大小的图像,用于检测图像中不同大小的脸部。较小的比例因子会导致更彻底的脸部搜索,但速度较慢,而较大的比例因子会导致搜索速度更快,但可能会遗漏一些脸部。

minNeighbors 参数指定每个候选矩形应该保留多少个邻居。该参数会影响检测到的脸部质量。数值越高,检测次数越少,质量越高。3~6是很好的参考取值。

minSize确定被检测对象的阈值大小。对于maxSize,则相反。

#10
faces = cascade.detectMultiScale(img_gray, 1.5, 5)

在图像中的面部周围绘制矩形。

#12-13-14-15
for (x,y,w,h) in faces: 
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2) 
        roi_gray = img_gray[y:y+h, x:x+w] 
        roi_color = img[y:y+h, x:x+w]

收听事件以结束程序。(在我们的例子中按下退出键)。

#19-20-21
k = cv2.waitKey(30) & 0xff
if k == 27: 
   break

结果:

阅读更多…

在 C++ 中使用 OpenCV 扭曲对象的视角:https://towardsdev.com/warping-an-objects-perspective-with-opencv-in-c-cbe971698ac5

从零开始的 AdaBoostAdaBoost 算法解释和实现:https://medium.com/mlearning-ai/adaboost-from-scratch-f8979d961948

参考

https://docs.opencv.org/3.4/db/d28/tutorial_cascade_classifier.html

https://www.geeksforgeeks.org/detect-cat-faces-in-real-time-using-python-opencv/

https://www.cs.cmu.edu/~efros/courses/LBMV07/Papers/viola-cvpr-01.pdf

免责声明:作者保留权利,不代表本站立场。如想了解更多和作者有关的信息可以查看页面右侧作者信息卡片。
反馈
to-top--btn