Implement Face Recognition with face_recognition Package: A Beginner Guide
OpenCV Tutorial
Implement Face Recognition with face_recognition Package: A Beginner Guide

face_recognition

Face recognition with face_recognition uses the dlib functionality for both

encoding the faces and calculating the distances for the encoded faces.

Therefore, you do not need to code the

face_encodings() and compare_faces() functions, but just make use of them.

The encode_face_fr.py script shows you how to create the 128D descriptor that

makes use of the face_recognition.face_encodings() function:

# Load image:

image = cv2.imread("jared_1.jpg")

# Convert image from BGR (OpenCV format) to RGB (face_recognition format):

image = image[:, :, ::-1]

# Calculate the encodings for every face of the image:

encodings = face_recognition.face_encodings(image)

# Show the first encoding:

print(encodings[0])

To see how to compare faces using face_recognition, the compare_faces_fr.py script

has been coded. The code is as follows:

# Load known images (remember that these images are loaded in RGB order):

known_image_1 = face_recognition.load_image_file("jared_1.jpg")

known_image_2 = face_recognition.load_image_file("jared_2.jpg")

known_image_3 = face_recognition.load_image_file("jared_3.jpg")

known_image_4 = face_recognition.load_image_file("obama.jpg")

# Crate names for each loaded image:

names = ["jared_1.jpg", "jared_2.jpg", "jared_3.jpg", "obama.jpg"]

# Load unknown image (this image is going to be compared against all the previous loaded images):

unknown_image = face_recognition.load_image_file("jared_4.jpg")

# Calculate the encodings for every of the images:

known_image_1_encoding = face_recognition.face_encodings(known_image_1)[0]

known_image_2_encoding = face_recognition.face_encodings(known_image_2)[0]

known_image_3_encoding = face_recognition.face_encodings(known_image_3)[0]

known_image_4_encoding = face_recognition.face_encodings(known_image_4)[0]

known_encodings = [known_image_1_encoding, known_image_2_encoding, known_image_3_encoding

unknown_encoding = face_recognition.face_encodings(unknown_image)[0]

# Compare the faces:

results = face_recognition.compare_faces(known_encodings, unknown_encoding)

# Print the results:

print(results)

The results obtained are [True, True, True, False]. Therefore, the first three loaded

images ("jared_1.jpg", "jared_2.jpg", and "jared_3.jpg") are considered to be the

same person as the unknown image ("jared_4.jpg"), while the fourth loaded image

("obama.jpg") is considered to be a different person.

Related

Understand Marker-based Augmented Reality in OpenCV: A Beginner Tutorial

Marker-based augmented reality In this section, we are going to see how marker-based augmented reality works. There are many libraries, algorithms, or packages that you can use to both generate and detect markers. In this sense, one that provides state-of-the-art performance in detecting markers is ArUco. ArUco automatically detects the markers and corrects possible errors. Additionally, ArUco proposes a solution to the occlusion problem by combining multiple markers with an occlusion mask, which is calculated by color segmentation. As previously commented, pose estimation is a key process in augmented reality applications. Pose estimation can be performed based on markers. The main benefit of using markers is that they can be both efficiently and robustly detected in the image where the four corners of the marker can be accurately derived. Finally, the camera pose can be obtained from the previously calculated four corners of the marker. Therefore, in next subsections, we will see how to create marker-based augmented reality applications, starting from creating both markers and dictionaries. Creating markers and dictionaries The first step when using ArUco is the creation of markers and dictionaries. Firstly, an ArUco marker is a square marker composed of external and internal cells (also called bits). The external cells are set to black, creating an external border that can be fast and robustly detected. The remaining cells (the internal cells) are used for coding the marker. ArUco markers can also be created with different sizes. The size of the marker indicates the number of internal cells related to the internal matrix. For example, a marker size of 5 x 5 (n=5) is composed of 25 internal cells. Additionally, you can also set the number of bits in the marker border. Secondly, a dictionary of markers is the set of markers considered to be used in a specific application. While previous libraries considered only fixed dictionaries, ArUco proposes an automatic method for generating the markers with the desired number of them and with the desired number of bits. In this sense, ArUco includes some predefined dictionaries covering many configurations in connection with the number of markers and the marker sizes. The first step to consider when creating your marker-based augmented reality application is to print the markers to use. In the aruco_create_markers.py script, we are creating some markers ready to print. The first step is to create the dictionary object. ArUco has some predefined dictionaries: DICT_4X4_50 = 0, DICT_4X4_100 = 1, DICT_4X4_250 = 2, DICT_4X4_1000 = 3, DICT_5X5_50 = 4, DICT_5X5_100 = 5, DICT_5X5_250 = 6, DICT_5X5_1000 = 7, DICT_6X6_50 = 8, DICT_6X6_100 = 9, DICT_6X6_250 = 10, DICT_6X6_1000 = 11, DICT_7X7_50 = 12, DICT_7X7_100 = 13, DICT_7X7_250 = 14, and DICT_7X7_1000 = 15. In this case, we will create a dictionary using the cv2.aruco.Dictionary_get() function composed of 250 markers. Each marker will have a size of 7 x 7 (n=7): aruco_dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_7X7_250) At this point, a marker can be drawn using the cv2.aruco.drawMarker() function, which returns the marker ready to be printed. The first parameter of cv2.aruco.drawMarker() is the dictionary object. The second parameter is the marker id, which ranges between 0 and 249, because our dictionary has 250 markers. The third parameter, sidePixels, is the size (in pixels) of the created marker image. The fourth (optional, by default 1) parameter is borderBits, which sets the number of bits in the marker borders. So, in this example, we are going to create three markers varying the number of bits in the marker borders: aruco_marker_1 = cv2.aruco.drawMarker(dictionary=aruco_dictionary, id=2, sidePixels=600, borderBits=1) […]

Perspective Transformation of an Image: A Simple Introduction

Perspective transformation of an image In order to correct the perspective (also known as perspective transformation), you will need to create the transformation matrix by making use of the cv2.getPerspectiveTransform() function, where a 3 x 3 matrix is constructed. This function needs four pairs of points (coordinates of a quadrangle in both the source and output image) and calculates a perspective transformation matrix from these points. Then, the M matrix is passed to cv2.warpPerspective(), where the source image is transformed by applying the specified matrix with a specified size, as shown in the following code: pts_1 = np.float32([[450, 65], [517, 65], [431, 164], [552, 164]]) pts_2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]]) M = cv2.getPerspectiveTransform(pts_1, pts_2) dst_image = cv2.warpPerspective(image, M, (300, 300)) Perspective transformation of an image In order to correct the perspective (also known as perspective transformation), you will need to create the transformation matrix by making use of the cv2.getPerspectiveTransform() function, where a 3 x 3 matrix is constructed. This function needs four pairs of points (coordinates of a quadrangle in both the source and output image) and calculates a perspective transformation matrix from these points. Then, the M matrix is passed to cv2.warpPerspective(), where the source image is transformed by applying the specified matrix with a specified size, as shown in the following code: pts_1 = np.float32([[450, 65], [517, 65], [431, 164], [552, 164]]) pts_2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]]) M = cv2.getPerspectiveTransform(pts_1, pts_2) dst_image = cv2.warpPerspective(image, M, (300, 300))

Smooth, Blur and Sharpen Images with Filters and Custom-made Kernels in OpenCV: A Completed Guide

Applying arbitrary kernels OpenCV provides the cv2.filter2D() function in order to apply an arbitrary kernel to an image, convolving the image with the provided kernel. In order to see how this function works, we should first build the kernel that we will use later. In this case, a 5 x 5 kernel will be used, as shown in the following code: kernel_averaging_5_5 = np.array([[0.04, 0.04, 0.04, 0.04, 0.04], [0.04, 0.04, 0.04, 0.04, 0.04], [0.04, 0.04, 0.04, 0.04, 0.04],[0.04, 0.04, 0.04, 0.04, 0.04], [0.04, 0.04, 0.04, 0.04, 0.04]]) This corresponds to a 5 x 5 averaging kernel. Additionally, you can also create the kernel like this: kernel_averaging_5_5 = np.ones((5, 5), np.float32) / 25 Then we apply the kernel to the source image by applying the aforementioned function, as shown in the following code: smooth_image_f2D = cv2.filter2D(image, -1, kernel_averaging_5_5) Now we have seen a way to apply an arbitrary kernel to an image. In the previous example, an averaging kernel was created to smooth the image. There are other ways to perform image smoothing (also known as image blurring) without having to create the kernel. Instead, some other parameters could be provided to the corresponding OpenCV function. In the smoothing_techniques.py script, you can see the full code for this previous example and for the next subsection. Smoothing images As previously mentioned, in the smoothing_techniques.py script you will see other common filtering techniques to perform a smoothing operation. Smoothing techniques are commonly used to reduce noise, and additionally, these techniques can also be applied to reduce the pixelated effect in low-resolution images. These techniques are commented as follows. You can see the output of this script in the following screenshot: In the preceding screenshot, you can see the effect of applying common kernels in image processing. Averaging filter You can use both cv2.blur() and cv2.boxFilter() to perform an averaging by convolving the image with a kernel, which can be unnormalized in the case of cv2.boxFilter(). They simply take the average of all the pixels under the kernel area and replace the central element with this average. You can control the kernel size and the anchor kernel (by default (-1,-1), meaning that the anchor is located at the kernel center). When the normalize parameter (by default True) of cv2.boxFilter() is equal to True, both functions perform the same operation. In this way, both functions smooth an image using the kernel, as shown in the following expression: In the case of the cv2.boxFilter() function: In the case of the cv2.blur() function: In other words, cv2.blur() always uses a normalized box filter, as shown in the following code: smooth_image_b = cv2.blur(image, (10, 10)) smooth_image_bfi = cv2.boxFilter(image, -1, (10, 10), normalize=True) In the preceding code, the two lines of code are equivalent. Gaussian filtering OpenCV provides the cv2.GaussianBlur() function, which blurs an image by using a Gaussian kernel. This kernel can be controlled using the following parameters: ksize (kernel size), sigmaX (standard deviation in the x-direction of the Gaussian kernel), and sigmaY (standard deviation in the y-direction of the Gaussian kernel). In order to know which kernel has been applied, you can make use of the cv2.getGaussianKernel() function. For example, in the following line of code, cv2.GaussianBlur() blurs the image using a Gaussian kernel of size (9, 9): […]

Rotating an Image in OpenCV: A Beginner Guide

Rotating an image In order to rotate the image, we make use of the cv.getRotationMatrix2D() function to build the 2 x 3 transformation matrix. This matrix rotates the image at the desired angle (in degrees), where positive values indicate a counterclockwise rotation. Both the center of rotation and the scale factor can also be adjusted. Using these elements in our example, the following transformation matrix is calculated: This expression has the following values: The following example builds the M transformation matrix to rotate 180 degrees with respect to the center of the image with a scale factor of 1 (without scaling). Afterwards, this M matrix is applied to the image, as follows: height, width = image.shape[:2] M = cv2.getRotationMatrix2D((width / 2.0, height / 2.0), 180, 1) dst_image = cv2.warpAffine(image, M, (width, height)) In order to rotate the image, we make use of the cv.getRotationMatrix2D() function to build the 2 x 3 transformation matrix. This matrix rotates the image at the desired angle (in degrees), where positive values indicate a counterclockwise rotation. Both the center of rotation and the scale factor can also be adjusted. Using these elements in our example, the following transformation matrix is calculated: This expression has the following values: The following example builds the M transformation matrix to rotate 180 degrees with respect to the center of the image with a scale factor of 1 (without scaling). Afterwards, this M matrix is applied to the image, as follows: height, width = image.shape[:2] M = cv2.getRotationMatrix2D((width / 2.0, height / 2.0), 180, 1) dst_image = cv2.warpAffine(image, M, (width, height))

Understand Thresholding Algorithms Using scikit-image

Introducing thresholding with scikit- image In order to test scikit-image, we are going to threshold a test image using Otsu's binarization algorithm. In order to try this method, the first step is to import the required packages. In this case, in connection with scikit-image as follows: from skimage.filters import threshold_otsu from skimage import img_as_ubyte The key code to apply Otsu's binarization algorithm with scikit-image is the following: thresh = threshold_otsu(gray_image) binary = gray_image > thresh binary = img_as_ubyte(binary) The threshold_otsu(gray_image) function returns the threshold value based on Otsu's binarization algorithm. Afterwards, with this value, the binary image is constructed (dtype= bool), which should be converted to 8-bit unsigned integer format (dtype= uint8) for proper visualization. The img_as_ubyte() function is used for this purpose. The full code for this example can be seen in the thresholding_scikit_image_otsu.py script. The output can be seen in the following screenshot: We will now try out some thresholding techniques with scikit-image. Trying out more thresholding techniques with scikit-image We are going to threshold a test image comparing Otsu's, triangle, Niblack's, and Sauvola's thresholding techniques. Otsu and triangle are global thresholding techniques, while Niblack and Sauvola are local thresholding techniques. Local thresholding techniques are considered a better approach when the background is not uniform. For more information about Niblack's and Sauvola's thresholding algorithms, see An Introduction to Digital Image Processing (1986) and Adaptive document image binarization (2000), respectively. The full code for this example can be seen in the thresholding_scikit_image_techniques.py script. In order to try these methods, the first step is to import the required packages. In this case, in connection with scikit-image as follows: from skimage.filters import (threshold_otsu, threshold_triangle, threshold_niblack, threshold_sauvola) from skimage import img_as_ubyte In order to perform the thresholding operations with scikit-image, we call each thresholding method (threshold_otsu(), threshold_niblack(), threshold_sauvola(), and threshold_triangle()): # Trying Otsu's scikit-image algorithm: thresh_otsu = threshold_otsu(gray_image) binary_otsu = gray_image > thresh_otsu binary_otsu = img_as_ubyte(binary_otsu) # Trying Niblack's scikit-image algorithm: thresh_niblack = threshold_niblack(gray_image, window_size=25, k=0.8) binary_niblack = gray_image > thresh_niblack binary_niblack = img_as_ubyte(binary_niblack) # Trying Sauvola's scikit-image algorithm: thresh_sauvola = threshold_sauvola(gray_image, window_size=25) binary_sauvola = gray_image > thresh_sauvola binary_sauvola = img_as_ubyte(binary_sauvola) # Trying triangle scikit-image algorithm: thresh_triangle = threshold_triangle(gray_image) binary_triangle = gray_image > thresh_triangle binary_triangle = img_as_ubyte(binary_triangle) The output can be seen in the next screenshot: […]

Splitting and Merging Image Channels in OpenCV: A Beginner Tutorial

OpenCV Sometimes, you have to work with specific channels on multichannel images. To do this, you have to split the multichannel image into several single-channel images. Additionally, once the processing has been done, you may want to create one multichannel image from different single-channel images. In order to both split and merge channels, you can use the cv2.split() and cv2.merge() functions, respectively. The cv2.split() function splits the source multichannel image into several single-channel images. The cv2.merge() function merges several single-channel images into a multichannel image. In the next example, splitting_and_merging.py, you will learn how to work with these two aforementioned functions. Using the cv2.split() function, if you want to get the three channels from a loaded BGR image, then you should use the following code: (b, g, r) = cv2.split(image) Using the cv2.merge() function, if you want to build the BGR image again from its three channels, then you should use the following code: image_copy = cv2.merge((b, g, r)) You should remember that cv2.split() is a time-consuming operation, and so you should only use it if strictly necessary; otherwise, you can use the NumPy functionality to work with specific channels. For example, if you want to get the blue channel of the image, you can do the following: b = image[:, :, 0] Additionally, you can eliminate (set to 0), some of the channels of a multichannel image. The resulting image will have the same number of channels, but with the 0 value in the corresponding channel; for example, if you want to eliminate the blue channel of a BGR image, you can use the following code: image_without_blue = image.copy() image_without_blue[:, :, 0] = 0 If you execute the splitting_and_merging.py script, you will see the following screenshot: In order to understand this screenshot, you should remember the additive properties of the RGB color space. For example, in connection with the subplot BGR without B, you can see that most of it is yellow. This is because green and red values yield yellow. Another key feature that you can see is the black subplots corresponding to the specific channels that we have set to 0.