uz_assignments/assignment6/cam.py

120 lines
3.4 KiB
Python

import cv2
import numpy as np
import os
import uz_framework.image as uz
IMAGES_FOLDER = './datam/me/'
def read_images(path):
# Get all the path to the images and save them in a list
image_paths = [os.path.join(path, f) for f in os.listdir(path)]
images = []
for image_path in image_paths:
# Read the image and convert to grayscale
image_pil = cv2.imread(image_path, 0)
# Convert the image format into numpy array
image = np.array(image_pil, 'uint8')
images.append(image)
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = []
for image in images:
# Detect face in the image
face = face_cascade.detectMultiScale(image, 1.3, 5)
for (x, y, w, h) in face:
# Crop the face out
H = 300
W = 280
y_offset = 20
x_offset = 30
face = image[y-y_offset:(y-y_offset)+H, x-x_offset:(x-x_offset)+W].copy()
faces.append(face)
return np.array(faces)
def train(faces):
# Construct PCA of the faces
# Reshape all the images into a single matrix of size (n, m)
# Downsample the images
fcc = np.array([])
for face in faces:
face = cv2.pyrDown(face)
face = face.reshape((face.shape[0] * face.shape[1]), 1)
if fcc.size == 0:
fcc = face
else:
fcc = np.hstack((fcc, face))
print(fcc.shape)
U, _, _, mean = uz.dual_PCA(fcc.T)
return U, mean
def recognize(U, mean):
# Open webcam stream
cam = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
while True:
# Read the frame
_, frame = cam.read()
# Convert to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect faces
face = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in face:
# Crop the face
H = 300
W = 280
y_offset = 20
x_offset = 30
face = gray[y-y_offset:(y-y_offset)+H, x-x_offset:(x-x_offset)+W].copy()
if face.shape[0] != H or face.shape[1] != W:
continue
# Project the face into the PCA subspace
# Project images into PCA subspace
# Downsample the image
face = cv2.pyrDown(face)
face = face.reshape(-1) # Reshape it into a vector
y_i = np.matmul(face - mean, U)
# Project images back into original subspace
x_i = np.matmul(y_i, U.T) + mean
# Compute the L2 norm between the original image and the reconstructed image
norm = np.linalg.norm(face - x_i)
# If the norm is less than 1000, then the face is recognized
if norm < 8000:
cv2.putText(frame, 'Recognized Gasper', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2)
# Plot the rectangle around the face
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
# Display the frame
cv2.imshow('frame', frame)
# Exit if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
def main():
faces = read_images(IMAGES_FOLDER)
U, mean = train(faces)
recognize(U, mean)
if __name__ == '__main__':
main()