import cv2
import os
import numpy as np


# This module contains all common functions that are called in tester.py file


# Given an image below function returns rectangle for face detected alongwith gray scale image
def faceDetection(test_img):
    gray_img = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY)  # convert color image to grayscale
    face_haar_cascade = cv2.CascadeClassifier('HaarCascade/haarcascade_frontalface_default.xml')  # Load haar classifier
    faces = face_haar_cascade.detectMultiScale(gray_img, scaleFactor=1.32,
                                               minNeighbors=5)  # detectMultiScale returns rectangles

    return faces, gray_img


# Given a directory below function returns part of gray_img which is face alongwith its label/ID
def labels_for_training_data(directory):
    faces = []
    faceID = []

    for path, subdirnames, filenames in os.walk(directory):
        for filename in filenames:
            if filename.startswith("."):
                print("Skipping system file")  # Skipping files that startwith .
                continue

            id = os.path.basename(path)  # fetching subdirectory names
            img_path = os.path.join(path, filename)  # fetching image path
            print("img_path:", img_path)
            print("id:", id)
            test_img = cv2.imread(img_path)  # loading each image one by one
            if test_img is None:
                print("Image not loaded properly")
                continue
            faces_rect, gray_img = faceDetection(
                test_img)  # Calling faceDetection function to return faces detected in particular image
            if len(faces_rect) != 1:
                continue  # Since we are assuming only single person images are being fed to classifier
            (x, y, w, h) = faces_rect[0]
            roi_gray = gray_img[y:y + w, x:x + h]  # cropping region of interest i.e. face area from grayscale image
            faces.append(roi_gray)
            faceID.append(int(id))
    return faces, faceID


# Below function trains haar classifier and takes faces,faceID returned by previous function as its arguments
def train_classifier(faces, faceID):
    face_recognizer = cv2.face.LBPHFaceRecognizer_create()
    face_recognizer.train(faces, np.array(faceID))
    return face_recognizer


# Below function draws bounding boxes around detected face in image
def draw_rect(test_img, face):
    (x, y, w, h) = face
    cv2.rectangle(test_img, (x, y), (x + w, y + h), (255, 0, 0), thickness=5)


# Below function writes name of person for detected label
def put_text(test_img, text, x, y):
    cv2.putText(test_img, text, (x, y), cv2.FONT_HERSHEY_DUPLEX, 2, (255, 0, 0), 4)

[((11, 15, 11, 57), 'cv2.cvtColor', 'cv2.cvtColor', ({(11, 28, 11, 36): 'test_img', (11, 38, 11, 56): 'cv2.COLOR_BGR2GRAY'}, {}), '(test_img, cv2.COLOR_BGR2GRAY)', False, 'import cv2\n'), ((12, 24, 12, 96), 'cv2.CascadeClassifier', 'cv2.CascadeClassifier', ({(12, 46, 12, 95): '"""HaarCascade/haarcascade_frontalface_default.xml"""'}, {}), "('HaarCascade/haarcascade_frontalface_default.xml')", False, 'import cv2\n'), ((24, 40, 24, 58), 'os.walk', 'os.walk', ({(24, 48, 24, 57): 'directory'}, {}), '(directory)', False, 'import os\n'), ((51, 22, 51, 58), 'cv2.face.LBPHFaceRecognizer_create', 'cv2.face.LBPHFaceRecognizer_create', ({}, {}), '()', False, 'import cv2\n'), ((59, 4, 59, 77), 'cv2.rectangle', 'cv2.rectangle', (), '', False, 'import cv2\n'), ((64, 4, 64, 83), 'cv2.putText', 'cv2.putText', ({(64, 16, 64, 24): 'test_img', (64, 26, 64, 30): 'text', (64, 32, 64, 38): '(x, y)', (64, 40, 64, 63): 'cv2.FONT_HERSHEY_DUPLEX', (64, 65, 64, 66): '(2)', (64, 68, 64, 79): '(255, 0, 0)', (64, 81, 64, 82): '(4)'}, {}), '(test_img, text, (x, y), cv2.FONT_HERSHEY_DUPLEX, 2, (255, 0, 0), 4)', False, 'import cv2\n'), ((52, 33, 52, 49), 'numpy.array', 'np.array', ({(52, 42, 52, 48): 'faceID'}, {}), '(faceID)', True, 'import numpy as np\n'), ((30, 17, 30, 39), 'os.path.basename', 'os.path.basename', ({(30, 34, 30, 38): 'path'}, {}), '(path)', False, 'import os\n'), ((31, 23, 31, 51), 'os.path.join', 'os.path.join', ({(31, 36, 31, 40): 'path', (31, 42, 31, 50): 'filename'}, {}), '(path, filename)', False, 'import os\n'), ((34, 23, 34, 43), 'cv2.imread', 'cv2.imread', ({(34, 34, 34, 42): 'img_path'}, {}), '(img_path)', False, 'import cv2\n')]