Hello Folks!!!! Bored with the old hairstyle and cannot go to your favorite salon during this lockdown?? Then, why don’t you create your own hairdresser at home. You must be wondering how is this possible?
Let’s check the below tutorial and it will surely amaze you !!!!!
In today’s tutorial, we are going our own OpenCV program to append a hairwig on your head.
The trick is quite simple. Firstly, we will be going to detect our face. Then crop the hair wig image and add it to your hairs and saving your filtered image at the end.
The underlying concept used here is Computer Vision and Image Processing.
In Computer Vision, computers or machines are made to gain high-level understanding from the input digital images or videos with the purpose of automating tasks that the human visual system can do. It uses many techniques and Image Processing is just one of them.
Image Processing is the field of enhancing the images by tuning many parameter and features of the images. So Image Processing is the subset of Computer Vision. Here, transformations are applied to an input image and an the resultant output image is returned. Some of these transformations are- sharpening, smoothing, stretching etc.
Here we will be using haar cascade file and OpenCV library.
Haar cascade can be used for face detection which is a machine learning algorithm where a cascade function is trained from a lot of positive and negative images. It is then used to detect objects in other images.
OpenCV already contains many pre-trained Haar classifiers such as smile which is used in this model.
To apply these pre-trained classifiers, follow the following steps:
- Load the XML file of required classifiers.
- Load image in gray-scale mode as OpenCV mostly operates in gray scale.
- Apply necessary classifiers on the image.
Importing the necessary files
We’ll be using four main libraries of python.
- “cv2” for video capturing, frame reading, pixel management, color management of the video,
- “NumPy” is used to do mathematical manipulation with the pixels of the video, flipping the order of matrices and
- “datetime” for delays and imported os library.
- “os” for performing operations on directory
import cv2 import date time import os import numpy as np
Now, I’ll be detecting the face and smile using the cascade file. For this, we need to load the required XML classifiers and our input image (or video) in grayscale mode.
cascade_face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # if you want to add sticker on image img = cv2.imread('image.png')
Function to detect the face
Now, we’ll find the face in the image. If faces are found, it returns the positions of detected faces as Rect(x,y,w,h). Once we get these locations, we can create a ROI for the face and apply smile detection on this ROI.
I have created a detection function that takes two arguments: the image and the grayscale i.e. black and white image. I have used haar cascade to detect the face and stored the result in face variable. x_face, y_face, w_face, h_face are 2 top coordinates and width , depth of face respectively. In the loop, we are importing the ear image and defining the area of interest in grayscale and coloured image.
# gray image of our face, original image: def detection(grayscale, img): #1.3 is the scale factor , 5 is te min neighbours face = cascade_face.detectMultiScale(grayscale, 1.3, 5) #4 corrdinates in faces for (x_face, y_face, w_face, h_face) in face: img_wig= cv2.imread('hair2.png',-1) ## adjusing the width & dept width, depth, _= img_wig.shape width= int(w_face + 0.1* width) depth= int(h_face* 2/3) img_wig= cv2.resize(img_wig, (width, depth)) ## coordinates centre_x= x_face+ w_face/2 x_wig= int(centre_x-width/2) y_wig= int(y_face- (depth*2/3) ) ##cropping if x_wig<0: x_wig=0 if y_wig<0 : y_wig=0 y2=int(y_wig+depth) if(y2>= img.shape): y2= img.shape x2= int(x_wig+width) if(x2>= img.shape): x2= img.shape img_wig= img_wig[0: y2-y_wig, 0:x2-x_wig] bg= img[y_wig: y2, x_wig: x2] sg = np.atleast_3d(255 - img_wig[:, :,3])/255.0 np.multiply(bg, sg, out=bg, casting="unsafe") np.add(bg, 255-img_wig[:, :,0:3] * np.atleast_3d(img_wig[:, :,3]), out=bg) img[y_wig: y2, x_wig: x2] = bg return img #return image
Here we are importing the hair image and resizing the image according to the required dimensions. We are finding the centre of face and the x,y coordinates to place wig at the desired location.
cv2.imread() method loads an image from the specified file. If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format) then this method returns an empty matrix.
cv2.resize() method resizes the image. Resizing an image means changing the dimensions of it, be it width alone, height alone or both. Also, the aspect ratio of the original image could be preserved in the resized image.and opencv provides cv2.resize function to resize the image.
Numpy provides the powerful data structure known as n-d array and function to manipulate that n-d array. This data structure is used by other library to represent complex data such as images. Therefore we have used numpy function to parse the image of tongue and replace the white colour by black. Note that white coordinates are [255,255,255] and black coordinates as [0, 0, and 0]. It will create a 3d array of all the pixel values. We are then multiplying both images and adding them, then saving back in the bg variable and storing the values in the image variable.
Functions of Numpy Used in computation :–
numpy.atleast_3d() function is used when we want to Convert inputs to arrays with at least three dimension. Scalar, 1 and 2 dimensional inputs are converted to 3-dimensional arrays, whilst higher-dimensional inputs are preserved. Input includes scalar, lists, lists of tuples, tuples, tuples of tuples, tuples of lists and ndarrays.
numpy.multiply() function is used when we want to compute the multiplication of two array. It returns the product of arr1 and arr2, element-wise.
numpy.add() function is used when we want to compute the addition of two array. It add arguments element-wise. If shape of two arrays are not same, that is
arr1.shape != arr2.shape, they must be broadcastable to a common shape (which may be the shape of one or the other).
Capturing the Image and calling the function to add sticker
Now, I have created a variable to capture the video and set the path to store the output file. If the file already exists, then we will update the path therefore, the code is placed in try catch block to handle these exceptions.
vc = cv2.VideoCapture(0) #path path= os.getcwd() # Create directory dirName = 'tempimage_folder' try: os.mkdir(dirName) except FileExistsError: print("Directory " , dirName , " already exists") path= path+'/'+dirName
Now, after creating the directory, we have to capture the image and convert it into grayscale using cv2.cvtColour() function.Then, we’ll pass the arguments in detection function and store the result in final variable.
After getting the result we’ll display the image using cv2.imshow() function and then save image with name and current date and time appended. We’ll save the file using the cv2.imwrite() function which writes the next video frame.
cv2.waitKey() is a keyboard binding function. Its argument is the time in milliseconds. The function waits for specified milliseconds for any keyboard event. If you press any key in that time, the program continues. If 0 is passed, it waits indefinitely for a key stroke. It can also be set to detect specific key strokes like, if key a is pressed etc which we will discuss below.
cv2.destroyallWindows() simply destroys all the windows we created. If you want to destroy any specific window, use the function cv2.destroyWindow() where you pass the exact window name as the argument.
cnt=0 while cnt<500: #read status of camera and frame _, img = vc.read() #convert image ot grayscale grayscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #reuslt from detection function final = detection(grayscale, img) if final is not None: cv2.imshow('Video', final) #name of our image, wiht current time , so that it has new name each time. string = "pic"+str(datetime.datetime.now())+".jpg" #save image cv2.imwrite(os.path.join(path, string),final) if cv2.waitKey(1) & 0xFF == ord('q'): break cnt+=1 vc.release() cv2.destroyAllWindows()
So guys, we have successfully created our own python program to add hair wig on our face using OpenCV and Image Processing.
Feel free to share your thoughts in the comments section.