Detect faces without eyebrows and jaw using opencv - python

I am trying to detect faces (specifically, faces with opened eyes) using OpenCV haar cascade classifier. However, I had a problem detecting the faces that do not have eyebrows and/or jaw, as shown in the following image. I had tried many haar cascade for face detection such as haarcascade_frontalface_default.xml, haarcascade_frontalface_alt_tree.xml, etc. But all of these did not work.
Here is my code:
import cv2
import os
import glob
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye_tree_eyeglasses.xml')
count = 0
path = "./test/*.png"
for index, filename in enumerate(glob.glob(path)):
img = cv2.imread(filename)
basename = os.path.splitext(os.path.basename(filename))[0]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
# cv2.rectangle(img,(x,y),(x+w, y+h),(255,0,0), 2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
if len(eyes) >= 2:
count = count + 1
output_dir = './test/output'
cv2.imwrite(f'{output_dir}/{basename}.png', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Thank you in advance!

Use facial landmarks with dlib, this method may work for you, see these two links:
facial-landmarks-dlib-opencv-python
opencv-face-recognition
Also, see this link:
dlib-and-deep-learning

If you have tensorflow installed you can use a neural net to detect faces which give much better accuracy than the simple haar classifier.
Here's an example using the MTCNN detector which uses tensorflow as the backend.
from mtcnn.mtcnn import MTCNN
from PIL import Image
import numpy as np
img = Image.open('6qNFu.png') # load the image
img = np.asarray(img, dtype='uint8') # convert to numpy array
img = img[:,:,0:3] # drop the alpha channel
detector = MTCNN() # initialize MTCNN detector
print(detector.detect_faces(img)) # use MTCNN detector to return bounding box and face metrics
Using the bounding box you can extract the face from the image. Note: if the face is truncated like in the instances above, it might return a negative coordinate which is an extrapolation of where it thinks the face might be.
Here is a the documentation on MTCNN library: https://pypi.org/project/mtcnn/
It also tells you how to install it.

Related

Can mediapipe generate facial landmarks for faces from the side?

I am trying to use mediapipe to generate facial landmarks using this code
faceModule = mediapipe.solutions.face_mesh
with faceModule.FaceMesh(static_image_mode=True) as faces:
# loading the image
image = cv2.imread(file_name)
# processing the face to extract the landmark points (468 point) for each x,y,z
results = faces.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
if results.multi_face_landmarks != None:
print("there is a face")
else:
frame = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(frame)
plt.show()
The vast majority of the images that result in results.multi_face_landmarks = None are faces from the side.
Is there a way to fix that?
I tried to search to find if anyone faced that issue before and i didn't find any.
Are facial landmarks not for faces from the side?

Crop bunch of images in a directory in python open cv

I have a bunch of images say 200 in a folder I want to crop all of them. I know the logic to loop through the images in the folder and perform cropping. I wrote a code for cropping of the single image but for multiple images, when I tried to loop through them it showing error.
This is for the single image. This is working fine
import numpy as np
import cv2
import os
count=0
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
img = cv2.imread('C:\\Users\\Sasidhar Mankala\\Desktop\\pythonproject\\DataBase creation\\Images\\85.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h+8, x:x+w+8]
crop = img[y-8: y+h+8 , x-8: x+w+8]
image_name = str(count)+'.png'
image_path = os.path.join('C:\\Users\\Sasidhar Mankala\\Desktop\\pythonproject\\DataBase creation\\Cropped_Images',image_name)
count += 1
cv2.imwrite(image_path,crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
For the multiple images, I got this far but this growing error
import numpy as np
import cv2
import os
count=0
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
directory = 'C:\\Users\\Sasidhar Mankala\\Desktop\\pythonproject\\DataBase creation\\Images'
for images in directory:
gray = cv2.cvtColor(images, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
# img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = images[y:y+h+8, x:x+w+8]
crop = images[y-8: y+h+8 , x-8: x+w+8]
image_name = str(count)+'.png'
image_path = os.path.join('C:\\Users\\Sasidhar Mankala\\Desktop\\pythonproject\\DataBase creation\\Cropped_Images',image_name)
count += 1
cv2.imwrite(image_path,crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
the error showing is
Traceback (most recent call last):
File "c:\Users\Sasidhar Mankala\Desktop\pythonproject\DataBase creation\crop.py", line 11, in
gray = cv2.cvtColor(images, cv2.COLOR_BGR2GRAY)
TypeError: Expected Ptr<cv::UMat> for argument 'src'
I think this is happening is because of cvtColor is expecting a specific path but I don't understand how to do that.
Please help me with this. Thanks in advance
You've to iterate on the images in your directory (feel free to substitute jpg if you have another format
import glob
for images in glob.glob(''.join([directory, r"\*.jpg"])):
# Your code...
In your previous code you were iterating over a string
The problem is this line
for images in directory:
You are not getting the path for each image.
To get the path for each image do:
import os
path_to_images = 'C:/Users/Sasidhar Mankala/Desktop/pythonproject/DataBase reation/Images/'
for imgName in os.listdir(path_to_images):
imgPath = path_to_images + imgName
os.listdir(directory) returns a list of all the filenames in that directory
Another error is in the input to cvtColor. It takes an image input not an image path. So:
image = cv2.imread(imgPath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
You were also trying to manipulate a path. Notice how in roi_color now is using the imported image and in your code it was trying to use what was supposed to be the image path (images).
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
# img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = image[y:y+h+8, x:x+w+8]
crop = image[y-8: y+h+8 , x-8: x+w+8]
image_name = str(count)+'.png'
image_path = os.path.join('C:\\Users\\Sasidhar Mankala\\Desktop\\pythonproject\\DataBase creation\\Cropped_Images',image_name)
count += 1
cv2.imwrite(image_path,crop)
cv2.waitKey(0)
cv2.destroyAllWindows()

how to inspect image using python

i want to match 2 image and detect the similarity.
i am trying using color filter concept can any one help me out which method should i follow.
i want to detect the color pattern in the image.
import cv2
import numpy as np
img = cv2.imread("img.jpg")
hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img1 = cv2.imread("img1.jpg")
img1=cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
lower_red = np.array([60,60,60])
upper_red=np.array([250,250,250])
mask=cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(img, img1, mask = mask)
#cv2.imshow('frame', img)
#cv2.imshow('mask', mask)
cv2.imshow('img', res)
can anyone suggest me which method can i use.
Refer this link for pil Link
import Image
import ImageChops
im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")
diff = ImageChops.difference(im2, im1)
also refer these existing questions posted in tensorflow
Checking images for similarity with OpenCV
Simple and fast method to compare images for similarity

How to correctly use cv2.imwrite to save an image in openCV with cv2.selectROI

I am trying out OpenCV's ROI function. With this I am trying to crop out a section of an image that I load. After that I am trying to save the image as well as show it. Showing it is not much of a problem, but saving it is. The image is being stored as a big black rectangle instead of the actual cropped image. Here is my code:
import cv2
import numpy as np
from skimage.transform import rescale, resize
if __name__ == '__main__' :
# Read image
im = cv2.imread("/Path/to/Image.jpg")
img = resize(im, (400,400), mode='reflect')
# Select ROI
r = cv2.selectROI(img)
# Crop image
imCrop = img[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]
# Save first, then Display cropped image
cv2.imwrite("../../Desktop/Image.jpg", imCrop) # This is where there seems to be a problem
cv2.imshow("im", imCrop)
cv2.waitKey(0)
Can some one please help?
cv2.selectROI returns the (x,y,w,h) values of a rectangle similar to cv2.boundingRect(). My guess is that the saved black rectangle is due to rounding issues when converting the bounding box coordinates to an int type. So just unpack the (x,y,w,h) coordinates directly and use Numpy slicing to extract the ROI. Here's a minimum working example to extract and save a ROI:
Input image -> Program to extract ROI -> Saved ROI
Code
import cv2
image = cv2.imread('1.jpg')
(x,y,w,h) = cv2.selectROI(image)
ROI = image[y:y+h, x:x+w]
cv2.imshow("ROI", ROI)
cv2.imwrite("ROI.png", ROI)
cv2.waitKey()

How can i get array from 'imshow()' in opencv?

I use opencv to open a camera, it shows face area croping in another window at once, so i have 2 windows in the same time. So i would like to show image and get array at once. Below is my script
import numpy as np
import cv2
# load clasifier from file
face_cascade = cv2.CascadeClassifier('cascades\haarcascade_frontalface_default.xml')
img = cv2.VideoCapture(0)
while(1):
#Read images
h,f=img.read()
gray = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
# create rectangle
cv2.rectangle(f,(x,y),(x+w,y+h),(255,255,255),)
# crop face area
roi_gray = gray[y:y+h, x:x+w]
# showing crop face area
cv2.imshow('crop',roi_gray)
#create window camera which name is img
cv2.imshow('img',f)
key = cv2.waitKey(200)
if key in [27, ord('Q'), ord('q')]:
break
How to get array from cv2.imshow('crop',roi_gray)? Thank you

Categories