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.
Related
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).
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)
https://imgur.com/a/zCmwUEf.jpg
this is the image from whom i am trying to extract text but unable to do so.
import contours
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Users\tan\tesseract\Tesseract-OCR\tesseract.exe'
# Opening the image & storing it in an image object
img = cv2.imread("C:/Users/tan/Desktop/my tppc bots/training challange - Copy/sample4.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (18, 18))
dilation = cv2.dilate(thresh1, rect_kernel, iterations=1)
contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
im2 = img.copy()
file = open("recognized.txt", "w+")
file.write("")
file.close()
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
rect = cv2.rectangle(im2, (x, y), (x + w, y + h), (0, 255, 0), 2)
cropped = im2[y:y + h, x:x + w]
file = open("recognized.txt", "a")
text = pytesseract.image_to_string(cropped)
file.write(text)
file.write("\n")
this is my script
when i run it, it execute fine but when i open the text file it doesnt show any texts there just empty.
am i doing something wrong?
if someone can help me that be great
thanks!
I have found easyocr lib promising here.
Import the libs
import numpy as np
import easyocr
import cv2
read the image file
reader = easyocr.Reader(['en'],gpu = False) # load once only in memory.
image_file_name='capImage.png' # this is the screen snap of your image
image = cv2.imread(image_file_name)
get the text from image
image_text=(reader.readtext(image,detail=0)[0]) # output came as D F7BE1
print(image_text.replace(" ","")) # removed the space and output is : DF7BE1
clean up options for image :
image = cv2.imread(image_file_name)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
sharpen_kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpen = cv2.filter2D(gray, -1, sharpen_kernel)
thresh = cv2.threshold(sharpen, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
height = 100
dim = (800, 800)
resized = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)
now utilize the images.
image_text=(reader.readtext(thresh,detail=0)[0])
print(image_text.replace(" ",""))
image_text=(reader.readtext(sharpen,detail=0)[0])
print(image_text.replace(" ",""))
output:
https://snag.gy/6MrLNi.jpg
The chin is a bit off in this photo.
https://snag.gy/ORZHSe.jpg
Not this one.
Difference in Code:
image = cv2.resize(image,(2170, 2894), interpolation = cv2.INTER_AREA)
The second one does not have this line.
Complete Source Code:
import cv2
import sys
import dlib
import numpy as np
from PIL import Image
import rawpy
# Get user supplied values
imagePath = sys.argv[1]
cascPath = "HS.xml"
pointOfInterestX = 200
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("okgood.dat")
raw = rawpy.imread(imagePath)
rgb = raw.postprocess()
image = Image.fromarray(rgb)
#image.save("WOO.jpg")
open_cv_image = np.array(image)
open_cv_image = open_cv_image[:, :, ::-1].copy()
image = open_cv_image
image = cv2.resize(image,(2170, 2894), interpolation = cv2.INTER_AREA)
widthO, heightO = image.shape[:2]
faceCascade = cv2.CascadeClassifier(cascPath)
# Read the image
#image = cv2.imread(imagePath)
gray = cv2.cvtColor((image), cv2.COLOR_RGB2BGR)
#height, width = image.shape[:2]
# Detect faces in the image
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=4,
minSize=(500, 500)
#flags = cv2.CV_HAAR_SCALE_IMAGE
)
newdigit = 0
def test():
for l in range(y, y+h):
for d in range(x, x+w):
# print(image[l,d])
font = cv2.FONT_HERSHEY_SIMPLEX
if all(item < 150 for item in image[l, d]):
cv2.putText(image,"here",(d,l), font, .2,(255,255,255),1,cv2.LINE_AA)
return l;
image[l,d] = [0,0,0]
###
### put hairline 121 pixels from the top.
###
def shape_to_np(shape, dtype="int"):
# initialize the list of (x, y)-coordinates
coords = np.zeros((68, 2), dtype=dtype)
# loop over the 68 facial landmarks and convert them
# to a 2-tuple of (x, y)-coordinates
for i in range(0, 68):
coords[i] = (shape.part(i).x, shape.part(i).y)
# return the list of (x, y)-coordinates
return coords
two = 1
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
print(str(len(faces)))
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
pointOfInterestX = test()
break
dets = detector(image, 1)
one = 0
pointOfEight = 0
for k, d in enumerate(dets):
shape = predictor(image, d)
shape = shape_to_np(shape)
for (x, y) in shape:
if one == 8:
pointOfEight = y
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(image,str(one),(x,y), font, .2,(255,255,255),1,cv2.LINE_AA)
one = one + 1
cv2.circle(image, (x, y), 1, (0, 0, 255), -1)
# loop over the (x, y)-coordinates for the facial landmarks
# and draw them on the image
new_dimensionX = heightO * 631 / (pointOfEight - pointOfInterestX)
new_dimensionY = widthO * 631 / (pointOfEight - pointOfInterestX)
print(str(new_dimensionY))
image = cv2.resize(image,(int(new_dimensionX), int(new_dimensionY)))
Rx = new_dimensionX / heightO
Ry = new_dimensionY / widthO
crop_img = image[int((pointOfInterestX * Rx)-121):int(new_dimensionY), 0:int(new_dimensionX-((Rx *pointOfInterestX)+121))]
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(image,"xxxx",(100,pointOfInterestX ), font, 4,(255,255,255),1,cv2.LINE_AA)
cv2.imshow("Faces found", crop_img)
cv2.imwrite("cropped.jpg", crop_img)
cv2.waitKey(0)
Towards the top you will see the line where I resize the image to 2170,2894. Like I said, with this line absent, the chin detection is accurate. With it, it is not. I need the chin detection accurate at this resolution.
Try to use DLIB's face detector, landmarks detector initialized with face detector ROI, and DLIB's detector ROI is different from OpenCV Haar cascade one. DLIB's landmark detector trained using ROI's from DLIB's face detector, and should work better with it.
I'm trying to detect a face and write down area with the face in a separate file.
How can I do it? I think that i must use "faces" (you can see this var in code). But how?
from ffnet import mlgraph, ffnet, tmlgraph, imlgraph
import pylab
import sys
import cv,cv2
import numpy
cascade = cv.Load('C:\opencv\data\haarcascades\haarcascade_frontalface_alt.xml')
def detect(image):
bitmap = cv.fromarray(image)
faces = cv.HaarDetectObjects(bitmap, cascade, cv.CreateMemStorage(0))
if faces:
for (x,y,w,h),n in faces:
cv2.rectangle(image,(x,y),(x+w,y+h),(255,255,255),3)
return image
if __name__ == "__main__":
cam = cv2.VideoCapture(0)
while 1:
_,frame =cam.read()
frame = numpy.asarray(detect(frame))
cv2.imshow("features", frame)
if cv2.waitKey(1) == 0x1b: # ESC
print 'ESC pressed. Exiting ...'
break
This following code should extract face in images and save faces on disk
def detect(image):
image_faces = []
bitmap = cv.fromarray(image)
faces = cv.HaarDetectObjects(bitmap, cascade, cv.CreateMemStorage(0))
if faces:
for (x,y,w,h),n in faces:
image_faces.append(image[y:(y+h), x:(x+w)])
#cv2.rectangle(image,(x,y),(x+w,y+h),(255,255,255),3)
return image_faces
if __name__ == "__main__":
cam = cv2.VideoCapture(0)
while 1:
_,frame =cam.read()
image_faces = []
image_faces = detect(frame)
for i, face in enumerate(image_faces):
cv2.imwrite("face-" + str(i) + ".jpg", face)
#cv2.imshow("features", frame)
if cv2.waitKey(1) == 0x1b: # ESC
print 'ESC pressed. Exiting ...'
break
Alternatively, with MTCNN and OpenCV(other dependencies including TensorFlow also required), you can:
1 Perform face detection(Input an image, output all boxes of detected faces):
from mtcnn.mtcnn import MTCNN
import cv2
face_detector = MTCNN()
img = cv2.imread("Anthony_Hopkins_0001.jpg")
detect_boxes = face_detector.detect_faces(img)
print(detect_boxes)
[{'box': [73, 69, 98, 123], 'confidence': 0.9996458292007446, 'keypoints': {'left_eye': (102, 116), 'right_eye': (150, 114), 'nose': (129, 142), 'mouth_left': (112, 168), 'mouth_right': (146, 167)}}]
2 save all detected faces to separate files:
for i in range(len(detect_boxes)):
box = detect_boxes[i]["box"]
face_img = img[box[1]:(box[1] + box[3]), box[0]:(box[0] + box[2])]
cv2.imwrite("face-{:03d}.jpg".format(i+1), face_img)
3 or Draw rectangles of all detected faces:
for box in detect_boxes:
box = box["box"]
pt1 = (box[0], box[1]) # top left
pt2 = (box[0] + box[2], box[1] + box[3]) # bottom right
cv2.rectangle(img, pt1, pt2, (0,255,0), 2)
cv2.imwrite("detected-boxes.jpg", img)
wtluo, great !
May I propose a slight modification of your code 2. ? Here it is:
for i, detected_box in enumerate(detect_boxes):
box = detected_box["box"]
face_img = img[ box[1]:box[1] + box[3], box[0]:box[0] + box[2] ]
cv2.imwrite("face-{:03d}.jpg".format(i+1), face_img)