import os
import cv2
from PIL import Image,ImageDraw
from datetime import datetime
import time

#detectFaces()返回图像中所有人脸的矩形坐标（矩形左上、右下顶点）
#使用haar特征的级联分类器haarcascade_frontalface_default.xml，在haarcascades目录下还有其他的训练好的xml文件可供选择。
#注：haarcascades目录下训练好的分类器必须以灰度图作为输入。
def DetectFaces(imagePath):
    cascPath = "haarcascade_frontalface_default.xml"
    faceCascade = cv2.CascadeClassifier(cascPath)

    img = cv2.imread(imagePath)
    #if语句：如果img维度为3，说明不是灰度图，先转化为灰度图gray，如果不为3，也就是2，原图就是灰度图
    if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        gray = img 

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.2,
        minNeighbors=5,
        minSize=(30, 30),
    )
    
    result = []
    for (x,y,w,h) in faces:
        result.append((x,y,x+w,y+h))
    
    print("Found {0} faces!".format(len(faces)))
    return result    
#    # Draw a rectangle around the faces
#    for (x, y, w, h) in faces:
#        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
#    
#    cv2.imshow("Faces found", image)
#    cv2.waitKey(0)

#在原图像上画矩形，框出所有人脸。
#调用Image模块的draw方法，Image.open获取图像句柄，ImageDraw.Draw获取该图像的draw实例，然后调用该draw实例的rectangle方法画矩形(矩形的坐标即
#detectFaces返回的坐标)，outline是矩形线条颜色(B,G,R)。
def DrawFaces(imagePath):
    faces = DetectFaces(imagePath)
    if faces:
        img = Image.open(imagePath)
        drawInstance = ImageDraw.Draw(img)
        for (x1,y1,x2,y2) in faces:
            drawInstance.rectangle((x1,y1,x2,y2), outline=(0,255,0))
        img.save('drawfaces_'+imagePath)

def DetectEyes(imagePath):
    cascPath = "haarcascade_eye.xml"
    eyeCascade = cv2.CascadeClassifier(cascPath)
#    faces = DetectFaces(imagePath)
    
    img = cv2.imread(imagePath)
    if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        gray = img
    
    eyes = eyeCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=2,
    )
    result = []
    for (x,y,w,h) in eyes:
        result.append((x,y,x+w,y+h))
    
    print("Found {0} eyes!".format(len(eyes)))

#    result = []
#    for (x1,x2,y1,y2) in faces:
#        roiGray = gray[y1:y2, x1:x2]
#        eyes = eyeCascade.detectMultiScale(
#            roiGray,
#            scaleFactor=1.1,
#            minNeighbors=2,
#        )
#        for (ex,ey,ew,eh) in eyes:
#            result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))
    
    return result

def DrawEyes(imagePath):
    eyes = DetectEyes(imagePath)
    if eyes:
        img = Image.open(imagePath)
        drawInstance = ImageDraw.Draw(img)
        for (x1,y1,x2,y2) in eyes:
            drawInstance.rectangle((x1,x2,y1,y2), outline = (0,255,0))
        img.save('draweyes_'+imagePath)
    
def SaveFaces(imagePath):
    faces = DetectFaces(imagePath)
    if faces:
        #将人脸保存在save_dir目录下。
        #Image模块：Image.open获取图像句柄，crop剪切图像(剪切的区域就是detectFaces返回的坐标)，save保存。
        save_dir = imagePath.split('.')[0]+"_faces"
        if not os.path.exists(save_dir):
            try:
                os.mkdir(save_dir)
            except OSError:
                pass
        
        count = 0
        for (x1,y1,x2,y2) in faces:
            fileName = os.path.join(save_dir,str(count)+".jpg")
            Image.open(imagePath).crop((x1,y1,x2,y2)).save(fileName)
            count+=1

if __name__ == "__main__":
    img="abba.png"
#    img="5a72d6ee6b46f.jpg"
    #SaveFaces("abba.png")
    DrawFaces(img)
    DrawEyes(img)