# Import the libraries
import cv2
import os
import numpy as np
[docs]class SIFT:
"""
Class that provides easy access to the SIFT algorithm.
"""
def __init__(self, nfeatures=0, nOctaveLayers=3, contrastThreshold=0.04,
edgeThreshold=10, sigma=1.6, distance=cv2.NORM_L2, crossCheck=False):
"""
Set the default values.
:param nfeatures: The number of features (default 0).
:param nOctaveLayers: The number of octave layers (default 3).
:param contrastThreshold: The contrast threshold (default 0.04).
:param edgeThreshold: The edge threshold (default 10).
:param sigma: The sigma value (default 1.6).
:param distance: The distance (default cv2.NORM_L2 - euclidean distance).
:param crossCheck: The cross check parameter (default false).
"""
# If the parameter is invalid get its default value
if nfeatures < 0:
nfeatures = 0
if nOctaveLayers < 0:
nOctaveLayers = 3
if contrastThreshold < 0.0:
contrastThreshold = 0.04
if edgeThreshold < 0:
edgeThreshold = 10
if sigma < 0.0:
sigma = 1.6
# Creates the SIFT object
self.faceRec = cv2.xfeatures2d.SIFT_create(
nfeatures=nfeatures,
nOctaveLayers=nOctaveLayers,
contrastThreshold=contrastThreshold,
edgeThreshold=edgeThreshold,
sigma=sigma)
# Creates the matcher object
self.matcher = cv2.BFMatcher(distance, crossCheck=crossCheck)
self.labels = []
self.algorithmTrained = False
[docs] def getAlgorithmName(self):
"""
Get the algorithm name.
:return: The algorithm name.
"""
return "Scale-Invariant Feature Transform (SIFT)"
[docs] def train(self, images, labels):
"""
Train the face recognition algorithm
:param images: A slice with all images for training.
:param labels: A slice with all labels corresponding to the images.
"""
self.labels = labels
for image in images:
# Detects and computes the keypoints and descriptors using the sift
# algorithm
keypoints, descriptors = self.faceRec.detectAndCompute(image, None)
# Creates an numpy array
clusters = np.array([descriptors])
# Add the array to the BFMatcher
self.matcher.add(clusters)
# Train: Does nothing for BruteForceMatcher though
self.matcher.train()
self.algorithmTrained = True
[docs] def predict(self, image):
"""
Predict the image. Given a new image this function will make the prediction.
:param image: The image we want to predict.
:return: The subject ID (label) and the confidence.
"""
if self.algorithmTrained is False:
print "The face recognition algorithm was not trained."
sys.exit()
# Detects and computes the keypoints and descriptors using the sift
# algorithm
keypoints, descriptors = self.faceRec.detectAndCompute(image, None)
# Get all matches based on the descriptors
matches = self.matcher.match(descriptors)
# Order by distance
matches = sorted(matches, key=lambda x: x.distance)
# Creates a results vector to store the number of similar points for
# each image on the training set
results = [0] * len(self.labels)
# Based on the matches vector we create the results vector that
# represents how many points this test image are similar to each image
# in the training set
for match in matches:
if match.imgIdx >= 0 and match.imgIdx < len(results):
results[match.imgIdx] += 1
else:
print "Error invalid index"
sys.exit()
# Index receives the position of the maximum value in the results
# vector (it means that this is the most similar image)
index = results.index(max(results))
# Calculate the confidence based on the number of matches and the max result
# The confidence range is: 0 - 100
# The closer to zero higher is the confidence
if len(matches) > 0:
confidence = 100.0 - \
((float(max(results)) * 100.0) / float(len(matches)))
else:
confidence = 0.0
return self.labels[index], confidence