本文正在参加 人工智能创作者扶持计划
今天学习的是OpenCV进行照片人脸检测,所有的参考博文、文献、视频、代码都会在文末附上链接或文件压缩包。
本文的目录如下:
@TOC
一、OpenCV 简介
1.什么.OpenCV
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,拥有丰富的常用图像处理函数库,采用C/C++语言编写,可以运行在Linux/Windows/Mac等操作系统上,能够快速的实现一些图像处理和识别的任务。此外,OpenCV还提供了Java、python、cuda等的使用接口、机器学习的基础算法调用,从而使得图像处理和图像分析变得更加易于上手,让开发人员更多的精力花在算法的设计上。
2.为什么使用OpenCV?
虽然 python 很强大,而且也有自己的图像处理库 PIL,但是相对于OpenCV 来讲,它还是弱小很多。跟很多开源软件一样 OpenCV 也提供了完善的 python 接口,非常便于调用。它包含了超过 2500 个算法和函数,几乎任何一个能想到的成熟算法都可以通过调用 OpenCV 的函数来实现,超级方便。
二、Opencv 进行照片人脸检测
1、代码
# -*- coding: utf-8 -*-
import cv2 as cv
def face_detect_demo(img):
img = cv.resize(img, dsize=(800, 800))
gary = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier("./opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml")#haarcascade_frontalface_default.xml")
face = face_detect.detectMultiScale(gary, 1.004, 28, 6, (60, 60), (70, 70))
for x, y, w, h in face:
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=4)
cv.imshow("result", img)
# img.save("result.jpg") # 保存图片
cv.imwrite(r"final_result.jpg", img)
img = cv.imread("photo.jpg")
face_detect_demo(img) # 检测单个图片
while True:
if ord("q") == cv.waitKey(1):
break
cv.destroyAllWindows()
2、代码解释
detectMultiScale()函数 详细解释
1. import cv2 as cv
首先导入我们所需要的必要包opencv,对应指令为import cv2 as cv,这里的as就相当于给这个模块起了个别名。
如果opencv还没有安装的话,可以在终端里面pip install opencv-python。
2. def face_detect_demo(img):
接着,我们定义一个函数face_detect_demo,这个函数有一个参数img,即我们要检测的图片,这是一个形参。
3. img = cv.resize(img, dsize=(800, 800))
调用cv里面的函数resize,改变图片的大小。
resize第一个参数是要处理的图片,第二个参数是你想要改成图片的大小,
这里的(800,800)就是改成800*800的这样一张图片。处理的结果再返回给img。
4. gary = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
接下来更改图片颜色,直接调用cvtColor函数,
同样,第一个参数是要处理的图片,第二个参数是要更改的颜色类型,
这里的颜色类型有很多种,我这里设置的是COLOR_BGR2GRAY类型。
前几步,可以理解为将图片标准化,即传入不同大小,不同颜色的图片可以转化成同一大小,同一颜色类型的图片。这样的操作好处在于后面调参数更容易。
5. face_detect = cv.CascadeClassifier("./opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml")
==重头戏来了!===,这是opencv官方已经训练好的一个人脸检测模型,直接调用就可以,非常方便!
文件链接:pan.baidu.com/s/1FV3NWT3V… 提取码:tsvd
文件和代码提取链接,也有一些其他训练好的模型,如果感兴趣的话你也可以试一试其他模型。
6. face = face_detect.detectMultiScale(gary, 1.004, 10, 0, (40, 40), (50, 50))
接着,我们检测图片中的人脸,face_detect.detectMultiScale,就是调用模型里的detectMultiScale。
detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]]) -> objects
第一个参数 image是要处理的图片,一般为灰度图像加快检测速度;
第二个参数 scaleFactor是表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%;比例越小,迭代的次数越多。
Haar cascade的工作原理是一种“滑动窗口”的方法,通过在图像中不断的“滑动检测窗口”来匹配人脸。
因为图像的像素有大有小,图像中的人脸因为远近不同也会有大有小,所以需要通过scaleFactor参数设置一个缩小的比例,对图像进行逐步缩小来检测,这个参数设置的越大,计算速度越快,但可能会错过了某个大小的人脸。
其实可以根据图像的像素值来设置此参数,像素大缩小的速度就可以快一点,通常在1~1.5之间。
那么,经过多次的迭代,实际会检测出很多很多个人脸,这一点可以通过把minNeighbors 设为0来验证。
第三个参数 minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors – 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框。
这里有点不太好理解,相邻矩形指的是对于同一张候选人脸(尚未确定)多次迭代后识别到的框,只有这个相邻框的个数大于自己设定的minneighbor,才会确定这个候选人脸框是正确的。
下面举例说明:
minNeighbors=0可以理解为每个人像只要被识别到一次就可以,因为一次对应一个方框。比如,参考博文中的这些图人脸检测,下图最右上角李斯被识别出1次,这个方框邻居数为0。
但假如minNeighbors=1,至少有一个邻居方框,那就意味着被识别出来至少两次。下图李斯没识别出来,因为她的识别结果中没有“邻居”;
minNeighbors=3,至少有3个邻居方框,那就意味着被识别出来至少4次。下图孟佳也没有识别出来,因为她的识别结果中只有1个“邻居”。
第四个参数 flag参数与旧的级联方法cvHaarDetectObjects中一样,新的级联中不用。(没用到这个参数)取任意值都可。但不能直接删掉。会报错。
error: OpenCV(4.7.0) :-1: error: (-5:Bad argument) in function 'detectMultiScale'
> Overload resolution failed:
> - Argument 'flags' is required to be an integer
> - Argument 'flags' is required to be an integer
第五个参数 minSize是最小矩形框大小,
第六个参数 maxSize是最大矩形框大小。这六个参数需要自己去调,以求最佳匹配。
detectMultiScale方法会直接用该模型检测图片,并返回多个x,y,w,h。(x,y)是左顶点的坐标,w是矩形框的宽度,h是矩形框的高度。
7. for x, y, w, h in face:
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=4)
cv.imshow("result", img)
cv.imwrite(r"final_result.jpg", img)
for循环的功能就是在原来的图片上面绘制矩形框啦,对应的函数是cv.rectangle,这里面的参数很简单就不一一介绍了。
cv.imshow进行展示,cv.imwrite进行保存,注意imwrite保存图片时,命名要加上.jpg
==函数到此结束,接下来是调用函数:==
8. img = cv.imread("photo.jpg")
face_detect_demo(img) # 检测单个图片
首先读取图片,把程序和图片放在一个文件夹,可以直接用名字去读,如果你没有放在一个文件家里面,要用绝对路径去读取。
调用上面写好的函数去检验人脸。
9. while True:
if ord("q") == cv.waitKey(1):
break
cv.destroyAllWindows()
最后做一个键盘的关联事件退出,,按下键盘q键会退出循环,程序结束。cv.destroyAllWindows销毁所有窗口。
3、效果分析
找了前几天微博之夜的图片,正面对镜头基本都能准确检测到人脸的位置。
但侧面对镜头未能准确检测到,那可是神仙姐姐啊!!! 有大神知道怎么调参数欢迎评论区指教!!!!
我这里用的是: face = face_detect.detectMultiScale(gary, 1.029, 3, 6, (90, 90), (120, 120))
参考博客及代码
opencv 官方开源代码链接:pan.baidu.com/s/1FV3NWT3V…
提取码:tsvd
最后,感谢各位前辈的分享,本文先写到这里,欢迎大家批评指正!