#以 anaconda 为容器安装:
conda install opencv
import os
import cv2
from PIL import Image,ImageDraw
定义人脸检测函数detectFaces(),检测图片中所有出现的人脸,并返回人脸的矩形坐标(矩形左上、右下顶点坐标)。使用上面提到的xml文件(haar特征),haarcascades目录下有好几个是关于人脸检测的文件,这里选择haarcascade_frontalface_default.xml,当然也可以使用其他的。另外需要注意的是,必须以灰度图作为haar分类器的输入。
def detectFaces(image_name):
img = cv2.imread(image_name)
face_cascade = cv2.CascadeClassifier("/anaconda/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml")
if img.ndim == 3:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img #if语句:如果img维度为3,说明不是灰度图,先转化为灰度图gray,如果不为3,也就是2,原图就是灰度图
faces = face_cascade.detectMultiScale(gray, 1.2, 5)#1.3和5是特征的最小、最大检测窗口,它改变检测结果也会改变
result = []
for (x,y,width,height) in faces:
result.append((x,y,x+width,y+height))
return result
上面的detectFaces函数我们获得了图片中所有人脸的坐标,在有些时候,我们希望把人脸截取出来,然后进行下一步操作(比如做人脸身份识别、表情识别等),保存人脸图的函数如下,使用了PIL的Image模块:
def saveFaces(image_name):
faces = detectFaces(image_name)
if faces:
#将人脸保存在save_dir目录下。
#Image模块:Image.open获取图像句柄,crop剪切图像(剪切的区域就是detectFaces返回的坐标),save保存。
save_dir = image_name.split('.')[0]+"_faces"
os.mkdir(save_dir)
count = 0
for (x1,y1,x2,y2) in faces:
file_name = os.path.join(save_dir,str(count)+".jpg")
Image.open(image_name).crop((x1,y1,x2,y2)).save(file_name)
count+=1
有些时候,为了展示或者方便观察,需要在原始图像上框出人脸,用矩形将人脸框出,这个功能的实现如下,主要用到PIL的ImageDraw模块(另外,opencv也有画矩形工具,也可以实现):
#在原图像上画矩形,框出所有人脸。
#调用Image模块的draw方法,Image.open获取图像句柄,ImageDraw.Draw获取该图像的draw实例,然后调用该draw实例的rectangle方法画矩形(矩形的坐标即
#detectFaces返回的坐标),outline是矩形线条颜色(B,G,R)。
#注:原始图像如果是灰度图,则去掉outline,因为灰度图没有RGB可言。drawEyes、detectSmiles也一样。
def drawFaces(image_name):
faces = detectFaces(image_name)
if faces:
img = Image.open(image_name)
draw_instance = ImageDraw.Draw(img)
for (x1,y1,x2,y2) in faces:
draw_instance.rectangle((x1,y1,x2,y2), outline=(255, 0,0))
img.save('drawfaces_'+image_name)
其他:
在haarcascades目录下,也有一些关于眼睛检测的xml文件。可以像函数detectFaces()那样,将检测face的xml文件换成检测eyes的xml文件即可。但是,由于眼睛在人脸上,我们往往是先检测出人脸,再细入地检测眼睛。故detectEyes可在detectFaces基础上来进行,代码中需要注意“相对坐标”。detectEyes()函数同样返回所有eyes在原图中的坐标。
def detectEyes(image_name):
eye_cascade = cv2.CascadeClassifier('/anaconda/share/OpenCV/haarcascades/haarcascade_eye.xml')
faces = detectFaces(image_name)
img = cv2.imread(image_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = []
for (x1,y1,x2,y2) in faces:
roi_gray = gray[y1:y2, x1:x2]
eyes = eye_cascade.detectMultiScale(roi_gray,1.3,2)
for (ex,ey,ew,eh) in eyes:
result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))
return result
def drawEyes(image_name):
eyes = detectEyes(image_name)
if eyes:
img = Image.open(image_name)
draw_instance = ImageDraw.Draw(img)
for (x1,y1,x2,y2) in eyes:
draw_instance.rectangle((x1,y1,x2,y2), outline=(0, 0,255))
img.save('draweyes_'+image_name)
直接运行: drawEyes(‘xxx.jpg’)
def detectSmiles(image_name):
img = cv2.imread(image_name)
smiles_cascade = cv2.CascadeClassifier("/anaconda/share/OpenCV/haarcascades/haarcascade_smile.xml")
if img.ndim == 3:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img #if语句:如果img维度为3,说明不是灰度图,先转化为灰度图gray,如果不为3,也就是2,原图就是灰度图
smiles = smiles_cascade.detectMultiScale(gray,4,5)
result = []
for (x,y,width,height) in smiles:
result.append((x,y,x+width,y+height))
return result
def drawSmiles(image_name):
smiles = detectSmiles(image_name)
if smiles:
img = Image.open(image_name)
draw_instance = ImageDraw.Draw(img)
for (x1,y1,x2,y2) in smiles:
draw_instance.rectangle((x1,y1,x2,y2), outline=(100, 100,0))
img.save('drawsmiles_'+image_name)