Combining Face Recognition with Face Emotion recognizer from webcam - python

I have a task where my job is to code a face recognizer which then analyses the pictures, compares it to a live webcam footage and displays the name of the person aswell as the dominant emotion.
What i currently have is this code snippet i took from this link: https://www.geeksforgeeks.org/face-detection-using-python-and-opencv-with-webcam/ and that i modified to this:
import cv2, sys, numpy, os
from keras.preprocessing.image import load_img, img_to_array
from keras.models import load_model
import matplotlib.pyplot as plt
import numpy as np
from deepface import DeepFace
size = 4
haar_file = 'haarcascade_frontalface_default.xml'
datasets = 'datasets'
# Part 1: Create fisherRecognizer
print('Recognizing Face Please Be in sufficient Lights...')
# Create a list of images and a list of corresponding names
(images, labels, names, id) = ([], [], {}, 0)
for (subdirs, dirs, files) in os.walk(datasets):
for subdir in dirs:
names[id] = subdir
subjectpath = os.path.join(datasets, subdir)
for filename in os.listdir(subjectpath):
path = subjectpath + '/' + filename
label = id
images.append(cv2.imread(path, 0))
labels.append(int(label))
id += 1
(width, height) = (130, 100)
# Create a Numpy array from the two lists above
(images, labels) = [numpy.array(lis) for lis in [images, labels]]
# OpenCV trains a model from the images
# NOTE FOR OpenCV2: remove '.face'
model = cv2.face.LBPHFaceRecognizer_create()
model.train(images, labels)
# Part 2: Use fisherRecognizer on camera stream
face_cascade = cv2.CascadeClassifier(haar_file)
webcam = cv2.VideoCapture(0)
emotion_dict = {
0: 'Surprise',
1: 'Happy',
2: 'Disgust',
3: 'Anger',
4: 'Sadness',
5: 'Fear',
6: 'Contempt'
}
while True:
(_, im) = webcam.read()
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(im, (x, y), (x + w, y + h), (255, 0, 0), 2)
face = gray[y:y + h, x:x + w]
face_resize = cv2.resize(face, (width, height))
# Try to recognize the face
prediction = model.predict(face_resize)
cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 3)
max_index = np.argmax(prediction[0])
emotions = ('angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral')
predicted_emotion = emotions[max_index]
cv2.putText(im, predicted_emotion, (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
if prediction[1]<500:
cv2.putText(im, '% s - %.0f' %
(names[prediction[0]], prediction[1]), (x-10, y-10),
cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 0))
else:
cv2.putText(im, 'not recognized',
(x-10, y-10), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 0))
cv2.imshow('OpenCV', im)
key = cv2.waitKey(10)
if key == 27:
break
however, when i try to run it, it only says that my emotion is angry, even though i am smiling or frowning. Does anyone have a suggestion to why this is? I'm eager to figure it out so comments are greatly appreciated

I got it to work now by using fer (pip install fer).

Related

how to recognize through both webcame and ipcamera using opencv

iam beginner in image processing i have trained my data using cafee model and recognize through webcame , but i have to connect both my webcamera as well as ipcamera(phone camera) ,Following is the code im using for recognition
import numpy as np
import pickle
import os
import cv2
import time
import imutils
curr_path = os.getcwd()
# print("Loading face detection model")
proto_path = os.path.join(curr_path, 'model', 'deploy.prototxt')
model_path = os.path.join(curr_path, 'model', 'res10_300x300_ssd_iter_140000.caffemodel')
face_detector = cv2.dnn.readNetFromCaffe(prototxt=proto_path, caffeModel=model_path)
# print("Loading face recognition model")
recognition_model = os.path.join(curr_path, 'model', 'openface_nn4.small2.v1.t7')
face_recognizer = cv2.dnn.readNetFromTorch(model=recognition_model)
recognizer = pickle.loads(open('recognizer.pickle', "rb").read())
le = pickle.loads(open('le.pickle', "rb").read())
print("Start capturing video....")
# address="http://192.168.210.242:8080/video"
# vid = cv2.VideoCapture(address)
vid = cv2.VideoCapture(0)
time.sleep(1)
while True:
ret, frame = vid.read()
frame = imutils.resize(frame, width=600)
(h, w) = frame.shape[:2]
image_blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0), False, False)
face_detector.setInput(image_blob)
face_detections = face_detector.forward()
for i in range(0, face_detections.shape[2]):
confidence = face_detections[0, 0, i, 2]
if confidence >= 0.5:
box = face_detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype('int')
face = frame[startY:endY, startX:endX]
(fH, fW) = face.shape[:2]
face_blob = cv2.dnn.blobFromImage(face, 1.0/255, (96, 96), (0, 0, 0), True, False)
face_recognizer.setInput(face_blob)
vec = face_recognizer.forward()
preds = recognizer.predict_proba(vec)[0]
j = np.argmax(preds)
proba = preds[j]
name = le.classes_[j]
text = "{}: {:.2f}".format(name, proba * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 0, 255), 2)
cv2.putText(frame, text, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
cv2.destroyAllWindows()
the coding is working good, One more thing if i run this individually(on webcame and ip camera) then it also works fine.but if i try to run both at the same time then the code is not working ,
please have a check on this issue thankyou.

My Code is only detecting single face only after applying For Loop also

I am trying to Detect Emotions using my model which takes images as an array, but my code is detecting faces using MTCNN in which the code is detecting only a single face, I have also applied for loop but still it is detecting single face only. Detecting Single face in Single Frame.
import keras
from keras.models import load_model
from time import sleep
from keras.preprocessing.image import img_to_array
from keras.preprocessing import image
import cv2
import numpy as np
from configs import Configs
from PIL import Image
from keras.applications.vgg16 import preprocess_input
from mtcnn.mtcnn import MTCNN
cfg = Configs()
detector = MTCNN()
model = load_model(cfg.model_path)
emotions = ['Angry', 'Disgust', 'Fear', 'Happy',
'Neutral', 'Pain', 'Sad', 'Surprise']
# Sample Video on which we have to Test
cap = cv2.VideoCapture(cfg.video_path)
while(cap.isOpened()):
ret, frame = cap.read()
faces = detector.detect_faces(frame)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if ret == False:
break
#for face in faces:
# x = faces[0]['box'][0]
# y = faces[0]['box'][1]
# w = faces[0]['box'][2]
# h = faces[0]['box'][3]
#face = x,y,w,h
for face in faces:
x = faces[0]['box'][0]
y = faces[0]['box'][1]
w = faces[0]['box'][2]
h = faces[0]['box'][3]
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 255), 2)
roi_gray = gray[y:y+h, x:x+w]
roi_gray = cv2.resize(roi_gray, (48, 48), interpolation=cv2.INTER_AREA)
if np.sum([roi_gray]) != 0:
roi = roi_gray.astype('float')/255.0
roi = img_to_array(roi)
roi = np.expand_dims(roi, axis=0)
prediction = model.predict(roi)[0]
label = emotions[prediction.argmax()]
label_position = (x, y)
cv2.putText(frame, label, label_position,
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
else:
cv2.putText(frame, 'No Faces', (30, 80),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
size = cv2.resize(frame[:, :, ::1], (560, 640))
cv2.imshow('Emotion Detector', size)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

cpp:1389 Error Assertion Failed detectmultiscale in face detection

Error:OpenCV(4.5.1) /tmp/pip-req-build-tk9iuyva/opencv/modules/objdetect/src/cascadedetect.cpp:1389: error: (-215:Assertion failed) scaleFactor > 1 && _image.depth() == CV_8U in function 'detectMultiScale'
I tried adding gray = np.array(gray, dtype='uint8') and the error disappears but the box that should appear when detecting a face does not appear
import tensorflow as tf
import keras
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.preprocessing.image import load_img
import numpy as np
import argparse
import cv2
import os
import matplotlib.pyplot as plt
%matplotlib inline
model = tf.keras.models.load_model("../input/modelh5/My_Model.h5")
images=['../input/face-mask1/examples/example_01.png', '../input/face-mask1/examples/example_02.png', '../input/face-mask1/examples/example_03.png' ]
face_cascade = cv2.CascadeClassifier('../input/haarcascade/haarcascade_frontalface_default.xml')
img = images[0] # Add path here
img = plt.imread(img,format='8UC1')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
# Draw the rectangle around each face
for (x, y, w, h) in faces:
face = img[y:y+h, x:x+w]
face = cv2.resize(face, (224, 224))
face = img_to_array(face)
face = preprocess_input(face)
face = np.expand_dims(face, axis=0)
(mask, withoutMask) = model.predict(face)[0]
mask = mask*100
withoutMask = withoutMask*100
font = cv2.FONT_HERSHEY_SIMPLEX
# Getting Text Size in pixel
print("Image Width: " , w)
textSize = cv2.getTextSize(text="No Mask: " + str("%.2f" % round(mask, 2)), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, thickness=3)
print("Text Width: " , textSize[0][0])
if mask > withoutMask:
cv2.putText(img,
text = "Mask: " + str("%.2f" % round(mask, 2)),
org = (x-5,y-15),
fontFace=font,
fontScale = (2*w)/textSize[0][0],
color = (0, 255, 0),
thickness = 3,
lineType = cv2.LINE_AA)
cv2.rectangle(img, (x, y), (x+w, y+h), (0,255,0), 5)
else:
cv2.putText(img,
text = "No Mask: " + str("%.2f" % round(withoutMask, 2)),
org = (x-5,y-15),
fontFace=font,
fontScale = (1.8*w)/textSize[0][0],
color = (255, 0, 0),
thickness = 3,
lineType = cv2.LINE_AA)
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 5)
# Display
plt.imshow(img)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

Real time face recognition ran slowly on Raspberry Pi3

I am using Raspberry Pi3 for face recognition and this is my code to detect the faces but the real time recognition ran slowly
cam = cv2.VideoCapture(0)
rec = cv2.face.LBPHFaceRecognizer_create();
rec.read(...'/data/recognizer/trainingData.yml')
getId = 0
font = cv2.FONT_HERSHEY_SIMPLEX
userId = 0
i = 0
while (cam.isOpened() and i<91):
i=i+1
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceDetect.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
getId, conf = rec.predict(gray[y:y + h, x:x + w]) # This will predict the id of the face
# print conf;
if conf < 50:
userId = getId
cv2.putText(img, "Detected", (x, y + h), font, 2, (0, 255, 0), 2)
record = Records.objects.get(id=userId)
record.is_present = True
record.save()
else:
cv2.putText(img, "Unknown", (x, y + h), font, 2, (0, 0, 255), 2)
# Printing that number below the face
# #Prams cam image, id, location,font style, color, stroke
cv2.imshow("Face", img)
cv2.waitKey(50)`
How to correct it please ? Thanks for your helping hand.
You should use threads to mazimize performance. imutils is a library that lets you use threading both on picamera and webcam capture. The issue here is that there are too many Input output operations being performed in between frames.
Here is the article that helped increase my fps:
https://www.pyimagesearch.com/2015/12/28/increasing-raspberry-pi-fps-with-python-and-opencv/
And this is the code you can add:
import imutils
from imutils.video.pivideostream import PiVideoStream
Then instead of cam = cv2.VideoCapture(0)
use cam = PiVideoStream().start()
and instead of ret, img = cam.read()
use im = cam.read()
and to release the camera use:
cam.stop()

Read multi images in a folder python

I am trying to read read multi images on a folder and do some processing. I have a code that extracts facial landmark coordinates. But I can apply this code to only one image. I want the script to work with all images in the folder. I have read some solutions but they didn't work for me. Can you tell me how can I apply a loop for this?
This is my code:
import numpy as np
import cv2
import dlib
import os
from glob import glob
mouth_matrice= open("C:/Users/faruk/Desktop/matrices/mouth.txt","w")
lefteye_matrice= open("C:/Users/faruk/Desktop/matrices/lefteye.txt","w")
righteye_matrice= open("C:/Users/faruk/Desktop/matrices/righteye.txt","w")
cascPath = ("C:/opencv/sources/data/haarcascades_cuda/haarcascade_frontalface_default.xml")
all_matrice= open("C:/Users/faruk/Desktop/matrices/all.txt","w")
#imagePath = ("C:/Users/faruk/Desktop/Dataset/Testing/342_spontaneous_smile_4 (2-17-2018 8-37-58 PM)/342_spontaneous_smile_4 357.jpg")
mypath=os.path.join("c:", os.sep, "Users", "faruk", "Desktop", "Dataset","Testing2")
PREDICTOR_PATH = ("C:/Users/faruk/Desktop/Working projects/facial-landmarks/shape_predictor_68_face_landmarks.dat")
JAWLINE_POINTS = list(range(0, 17))
RIGHT_EYEBROW_POINTS = list(range(17, 22))
LEFT_EYEBROW_POINTS = list(range(22, 27))
NOSE_POINTS = list(range(27, 36))
#RIGHT_EYE_POINTS = list(range(36, 42))
RIGHT_EYE_POINTS = list([36,39])
ALL_POINTS= list([36,39,42,45,48,51,54,57])
##LEFT_EYE_POINTS = list(range(42, 48))
LEFT_EYE_POINTS = list([42, 45])
##MOUTH_OUTLINE_POINTS = list(range(48, 61))
MOUTH_OUTLINE_POINTS = list([48,51,54,57])
MOUTH_INNER_POINTS = list(range(61, 68))
# Create the haar cascade
faceCascade = cv2.CascadeClassifier(cascPath)
predictor = dlib.shape_predictor(PREDICTOR_PATH)
# Read the image
cv2.namedWindow('Landmarks found',cv2.WINDOW_NORMAL)
cv2.resizeWindow('Landmarks found', 800,800)
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Detect faces in the image
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.05,
minNeighbors=5,
minSize=(100, 100),
flags=cv2.CASCADE_SCALE_IMAGE
)
print("Found {0} faces!".format(len(faces)))
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# Converting the OpenCV rectangle coordinates to Dlib rectangle
dlib_rect = dlib.rectangle(int(x), int(y), int(x + w), int(y + h))
landmarks = np.matrix([[p.x, p.y]
for p in predictor(image, dlib_rect).parts()])
#landmarks_display = landmarks[LEFT_EYE_POINTS]
landmarks_display = np.matrix(landmarks[ALL_POINTS])
for idx, point in enumerate(landmarks_display):
pos = (point[0, 0], point[0, 1])
cv2.circle(image, pos, 2, color=(0, 255, 255), thickness=-1)
np.savetxt(all_matrice,landmarks_display,fmt='%.f',newline=',')
all_matrice.close()
# Draw a rectangle around the faces
cv2.imshow("Landmarks found", image)
cv2.waitKey(0)
You can use something like this to get paths of all images in a directory:
import os
# Folder with images
directory = 'c:/users/username/path/'
for filename in os.listdir(directory):
if filename.endswith(".jpg"):
image_path = os.path.join(directory, filename)
# Your code
continue
else:
continue
You need to add your code and process each path.
Hope this helps.
Edit:
I have no way to test it and it certainly needs a cleanup but might just work. Not sure what image extensions you want to include so i only included jpg.
import os
import numpy as np
import cv2
import dlib
# Chage directory path to the path of your image folder
directory = 'c:/users/admin/desktop/'
mouth_matrice= open("C:/Users/faruk/Desktop/matrices/mouth.txt","w")
lefteye_matrice= open("C:/Users/faruk/Desktop/matrices/lefteye.txt","w")
righteye_matrice= open("C:/Users/faruk/Desktop/matrices/righteye.txt","w")
cascPath = ("C:/opencv/sources/data/haarcascades_cuda/haarcascade_frontalface_default.xml")
all_matrice= open("C:/Users/faruk/Desktop/matrices/all.txt","w")
mypath=os.path.join("c:", os.sep, "Users", "faruk", "Desktop", "Dataset","Testing2")
PREDICTOR_PATH = ("C:/Users/faruk/Desktop/Working projects/facial-landmarks/shape_predictor_68_face_landmarks.dat")
JAWLINE_POINTS = list(range(0, 17))
RIGHT_EYEBROW_POINTS = list(range(17, 22))
LEFT_EYEBROW_POINTS = list(range(22, 27))
NOSE_POINTS = list(range(27, 36))
#RIGHT_EYE_POINTS = list(range(36, 42))
RIGHT_EYE_POINTS = list([36,39])
ALL_POINTS= list([36,39,42,45,48,51,54,57])
##LEFT_EYE_POINTS = list(range(42, 48))
LEFT_EYE_POINTS = list([42, 45])
##MOUTH_OUTLINE_POINTS = list(range(48, 61))
MOUTH_OUTLINE_POINTS = list([48,51,54,57])
MOUTH_INNER_POINTS = list(range(61, 68))
# Create the haar cascade
faceCascade = cv2.CascadeClassifier(cascPath)
predictor = dlib.shape_predictor(PREDICTOR_PATH)
for filename in os.listdir(directory):
if filename.endswith(".jpg"):
imagePath=os.path.join(directory, filename)
cv2.namedWindow('Landmarks found',cv2.WINDOW_NORMAL)
cv2.resizeWindow('Landmarks found', 800,800)
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Detect faces in the image
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.05,
minNeighbors=5,
minSize=(100, 100),
flags=cv2.CASCADE_SCALE_IMAGE
)
print("Found {0} faces!".format(len(faces)))
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# Converting the OpenCV rectangle coordinates to Dlib rectangle
dlib_rect = dlib.rectangle(int(x), int(y), int(x + w), int(y + h))
landmarks = np.matrix([[p.x, p.y] for p in predictor(image, dlib_rect).parts()])
#landmarks_display = landmarks[LEFT_EYE_POINTS]
landmarks_display = np.matrix(landmarks[ALL_POINTS])
for idx, point in enumerate(landmarks_display):
pos = (point[0, 0], point[0, 1])
cv2.circle(image, pos, 2, color=(0, 255, 255), thickness=-1)
np.savetxt(all_matrice,landmarks_display,fmt='%.f',newline=',')
all_matrice.close()
# Draw a rectangle around the faces
cv2.imshow("Landmarks found", image)
cv2.waitKey(0)
continue
else:
continue
P.s You should try and learn basic programming concepts before you try to tackle something like face recognition or image processing.

Categories

Resources