1.4. 人脸检测
人脸检测的任务是从一个图像中寻找出人脸所在的位置和大小。0penCV提供了级联分类器(CascadeClassifier) 和人脸特征数据,只用少量代码就能实现人脸检测功能。
在本小节中,将学习编写几个简单的人脸检测程序,以此掌握在0penCV中操作图像、视频和摄像头的方法。
1.准备工作
在本地磁盘新建目录“BaseOpenCV”作为项目目录,从原书提供的“资源包/第32课/”中把“人脸检测”文件夹中的子目录和文件拷贝到新建的项目目录中,这是准备好的用于检测的人脸图像、视频和人脸(正脸)特征数据文件。 下面编写的人脸检测程序也存放在这个文件夹中。
2.检测图像中的人脸
在VSCode环境中,打开项目目录,新建一个空白源文件 ,以detect_image.jl作为文件名保存到“BaseOpenCV”中,然后编写程序检测图像中的人脸(正脸),具体过程如下。
(1) 导入 cv2 库。
using PyCall cv2=pyimport("cv2") |
(2) 从文件中加载一个含有人脸的图像,并转换得到一个灰度图像。
img = cv2.imread("images/face1.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
说明:OpenCV提供的cvtColor()方法是用于转换图像的色彩空间,使用cv2.OLOR_BGR2GRAY参数可以将一个彩色图像转换为灰度图像。
(3) 利用人脸特征数据创建一个人脸检测器(CascadeClassifier类的实例),然后调用该实例的detectMultiScale()方法检测图像中的人脸区域,将检测结果返回给变量faces。
file = "haarcascade_frontalface_default.xml" face_cascade = cv2.CascadeClassifier(file) faces = face_cascade.detectMultiScale(gray, 1.3, 5) |
说明:在调用detectMultiScale( )方法的参数中,第1个参数是一个灰度图像;第2个参数表示在前后两次相继的扫描中,搜索窗口的比例系数(默认为l.1,即每次搜索窗口依次扩大1的0;第3个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。
(4) 在检测图像中的每一个人脸区域画上矩形框。
#Julia数组是列主数组,而cv需要行主数组。 #反转维度,然后使用PyReverseDims数组 rimg = permutedims(img, ndims(img):-1:1) pyimg = PyReverseDims(rimg) for i in 1:size(faces)[1] x=faces[i,1] y=faces[i,2] w=faces[i,3] h=faces[i,4] cv2.rectangle(pyimg, (x, y), (x+w, y+h), (255, 0, 0), 3) end |
说明:检测出的人脸区域是一个矩形,由左上角坐标(x,y)和矩形的宽度w和高度h来确定。利用cv2.rectangle()方法可以在图像上画出一个矩形,该方法的第1个参数是图像,第2个参数是矩形的左上角坐标(x,y),第3个参数是矩形的右下角坐标(x+w,y+h),第4个参数是线条的颜色,第5个参数是线条的宽度。
注:以上代码中的for循环,python代码是这样写的
for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 3) |
为什么这样遍历faces中的元素?我们首先看一下faces是什么。通过type(faces)方法,我们可以获得faces的类型是”numpy.ndarray“, 这个ndarray(全称The N-dimensional array)是存储着相同类型和大小的元素的多维数组,再通过faces.shape,可知其是一个(3,4)的数组,for (x, y, w, h) in faces的结果,是遍历faces的每行,并将每行的4个元素值分别赋值给x, y, w, h四个变量。
我们再来看在julia中,faces是什么。通过前面我们提到过typeof(faces),我们可以获得faces的类型是“Matrix{Int32} “,是一个元素为Int32类型的矩阵。但是julia的矩阵是列主存储的,因此无法默认以 “行“遍历的方式访问,因此人脸检测的juli代码中,对这一处进行了改写。其中size()方法与python的shape一样,可以获得数组的真实维度值,而纬度值是一个元组类型,然后可以循环访问维度值的第一维,即矩阵的”行“,再将每行的元素值赋值给x,y,w,h四个遍历。
- 拓展知识:
关于在juia中以循环方式对矩阵元素的访问(也称迭代),这里再做进一步的拓展说明。
首先我们构造一个3x4的矩阵
julia> m = [10i+j for i=1:3, j=1:4] 3×4 Matrix{Int64}: 11 12 13 14 21 22 23 24 31 32 33 34 |
按照人脸检测的代码方式,我们可以这样遍历这个矩阵:
julia> for i=1:size(m)[1] x= m[i,1] y= m[i,2] w= m[i,3] h= m[i,4] println(x+1," ",y+1," ",w+1," ",h+1) end 输出结果: 12 13 14 15 22 23 24 25 32 33 34 35 |
当然我们还可以这样写:
julia> for i=1:size(m)[1] x,y,w,h=m[i,1:4] println(x+1," ",y+1," ",w+1," ",h+1) end |
我们还可以这样写:
julia> for i=1:size(m,1) x,y,w,h=m[i,1:4] println(x+1," ",y+1," ",w+1," ",h+1) end |
我们还可以这样写:
julia> for i=1:size(m,1) x,y,w,h=m[i,:] println(x+1," ",y+1," ",w+1," ",h+1) end |
还有更花式的写法:
julia> for row in eachrow(m) x,y,w,h=row println(x+1," ",y+1," ",w+1," ",h+1) end |
以上各种写法,哪个是性能最好的写法?大家可以研究一下。
(5) 把标注矩形框后的图像显示到窗口。
cv2.imshow("Image", pyimg) |
(6) 等待用户按下任意按键,之后销毁所有窗口。
cv2.waitKey(0) cv2.destroyAllWindows() |
至此,人脸检测程序编写完毕。运行程序,结果如图所示 。
标签:python,检测,图像,cv2,julia,OpenCV,人脸,faces From: https://www.cnblogs.com/zjzkiss/p/16754086.html