Public functions
get_known_identifiers
Return the list of known identifiers.
View Source
def get_known_identifiers(self):
"""Return the list of known identifiers."""
return list(self.__kids.keys())
create_identifier
Create a new identifier and add it in the list of known ones.
Returns
- (str) new identifier name
Parameters
View Source
def create_identifier(self, nb_img=ImagesFIFO.DEFAULT_QUEUE_SIZE):
"""Create a new identifier and add it in the list of known ones.
:return: (str) new identifier name
"""
pid = 'id{:03d}'.format(self.__id_idx)
self.__kids[pid] = ImagesFIFO(nb_img)
self.__id_idx += 1
return pid
remove_identifier
Remove an identifier of the list of known ones.
Parameters
View Source
def remove_identifier(self, kid):
"""Remove an identifier of the list of known ones.
:param kid: (str) An identifier
"""
if kid in self.__kids:
del self.__kids[kid]
add_image
Add an image to the known ones of the given identifier.
Parameters
- kid: (str) An identifier
- image: (sppasImage)
- reference: (bool) This is the reference image for this kid
Raises
KeyError, TypeError
View Source
def add_image(self, kid, image, reference=False):
"""Add an image to the known ones of the given identifier.
:param kid: (str) An identifier
:param image: (sppasImage)
:param reference: (bool) This is the reference image for this kid
:raise: KeyError, TypeError
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
self.__kids[kid].add(image, reference)
get_nb_images
Return the number of known images of the given identifier.
Parameters
Returns
View Source
def get_nb_images(self, kid):
"""Return the number of known images of the given identifier.
:param kid: (str) An identifier
:return: (int)
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
return len(self.__kids[kid])
get_ref_image
Return the reference image of the given identifier.
Parameters
Returns
View Source
def get_ref_image(self, kid):
"""Return the reference image of the given identifier.
:param kid: (str) An identifier
:return: (sppasImage or None)
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
return self.__kids[kid].get_ref_image()
get_cur_coords
Return the current coordinates of an identifier or None if unknown.
Parameters
Raises
KeyError
Returns
View Source
def get_cur_coords(self, kid):
"""Return the current coordinates of an identifier or None if unknown.
:param kid: (str) An identifier
:raise: KeyError
:return: (sppasCoords or None)
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
return self.__kids[kid].get_cur_coords()
set_cur_coords
Set the current coordinates for an identifier.
Parameters
- kid: (str) An identifier
- coords: (sppasCoords)
Raises
KeyError, TypeError
View Source
def set_cur_coords(self, kid, coords):
"""Set the current coordinates for an identifier.
:param kid: (str) An identifier
:param coords: (sppasCoords)
:raise: KeyError, TypeError
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
self.__kids[kid].set_cur_coords(coords)
get_ref_coords
Return the reference coordinates of an identifier or None if unknown.
Parameters
Raises
KeyError
View Source
def get_ref_coords(self, kid):
"""Return the reference coordinates of an identifier or None if unknown.
:param kid: (str) An identifier
:raise: KeyError
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
return self.__kids[kid].get_ref_coords()
set_ref_coords
Set the reference coordinates of an identifier.
Parameters
- kid: (str) An identifier
- coords: (sppasCoords)
Raises
KeyError, TypeError
View Source
def set_ref_coords(self, kid, coords):
"""Set the reference coordinates of an identifier.
:param kid: (str) An identifier
:param coords: (sppasCoords)
:raise: KeyError, TypeError
"""
if kid not in self.__kids:
raise sppasKeyError(kid, 'dict(ImagesFIFO)')
self.__kids[kid].set_ref_coords(coords)
enable_face_recognition
Enable or disable the automatic recognizer.
Parameters
View Source
def enable_face_recognition(self, value=True):
"""Enable or disable the automatic recognizer.
:param value: (bool)
"""
self.__fr = bool(value)
set_score_level
Fix threshold score for the identification measure.
Parameters
- value: (float) Value in range [0., 1.]
View Source
def set_score_level(self, value):
"""Fix threshold score for the identification measure.
:param value: (float) Value in range [0., 1.]
"""
value = float(value)
if value < 0.0 or value > 1.0:
raise IntervalRangeException(value, 0, 1)
self.__score_level = value
compare_kids_coords
Return a similarity score between two known identifiers.
Returns
- (float) Return 0. if no similarity or if eval not done
Parameters
View Source
def compare_kids_coords(self, kid1, kid2):
"""Return a similarity score between two known identifiers.
:return: (float) Return 0. if no similarity or if eval not done
"""
r1 = self.__kids[kid1].get_ref_coords()
r2 = self.__kids[kid2].get_ref_coords()
if r1 is not None and r2 is not None:
cc = sppasCoordsCompare(r1, r2)
ccr = cc.compare_coords()
else:
ccr = 0.0
l1 = self.__kids[kid1].get_cur_coords()
l2 = self.__kids[kid2].get_cur_coords()
if l1 is not None and l2 is not None:
cc = sppasCoordsCompare(l1, l2)
ccl = cc.compare_coords()
else:
ccl = 0.0
return (ccr + ccl) / 2.0
compare_kids_images
Return a similarity score between two known identifiers.
Returns
- (float) Return 0. if no similarity or if eval not done
Parameters
View Source
def compare_kids_images(self, kid1, kid2):
"""Return a similarity score between two known identifiers.
:return: (float) Return 0. if no similarity or if eval not done
"""
r1 = self.__kids[kid1].get_ref_image()
r2 = self.__kids[kid2].get_ref_image()
if r1 is not None and r2 is not None:
ic = sppasImageCompare(r1, r2)
return ic.score()
return 0.0
identify
Among the known identifiers, who matches the given image/coords.
Should return None if none of the known ids is recognized.
Parameters
- image: (sppasImage)
- coords: (sppasCoords)
Returns
- (kid, score) or (None, 0.)
View Source
def identify(self, image=None, coords=None):
"""Among the known identifiers, who matches the given image/coords.
Should return None if none of the known ids is recognized.
:param image: (sppasImage)
:param coords: (sppasCoords)
:return: (kid, score) or (None, 0.)
"""
kid = None
score = 0.0
if len(self.__kids) > 0:
if image is not None:
if self.__recognizer is not None:
kid, score = self.predict_recognizer(image)
if kid is None:
kid, score = self.predict_compare_images(image)
if coords is not None:
p, s = self.predict_compare_coords(coords)
if kid is None:
kid = p
score = s
elif p is not None:
if kid == p:
score = max(score, s)
elif score > s:
score = score / 2.0
else:
kid = p
score = s / 2.0
return (kid, score)
predict_compare_images
Compare the given image to the existing ones.
Evaluate similarity of image contents (very very low).
Parameters
- image: (sppasImage) The image to compare with
Returns
- tuple(kid, score) or (None, 0.)
View Source
def predict_compare_images(self, image):
"""Compare the given image to the existing ones.
Evaluate similarity of image contents (very very low).
:param image: (sppasImage) The image to compare with
:return: tuple(kid, score) or (None, 0.)
"""
scores = dict()
sc = None
for ref_name in self.__kids:
ref_img = self.__kids[ref_name].get_ref_image()
if ref_img is not None:
cmp = sppasImageCompare(image, ref_img)
areas = cmp.compare_areas()
sizes = cmp.compare_sizes()
mse = cmp.compare_with_mse()
kld = cmp.compare_with_kld()
scx = 0.4 * mse + 0.3 * kld + 0.15 * areas + 0.15 * sizes
if sc is not None:
sc = (sc + scx) / 2.0
else:
sc = scx
if sc is None:
sc = 0.0
scores[ref_name] = sc
scores = collections.Counter(scores)
sorted_scores = scores.most_common()
if sorted_scores[0][1] > self.__score_level:
return sorted_scores[0]
return (None, 0.0)
predict_compare_coords
Compare the given coords to the existing ones.
Parameters
- coords: (sppasCoords) The coords to compare with
Returns
- tuple(kid, score) or (None, 0.)
View Source
def predict_compare_coords(self, coords):
"""Compare the given coords to the existing ones.
:param coords: (sppasCoords) The coords to compare with
:return: tuple(kid, score) or (None, 0.)
"""
scores = dict()
for ref_name in self.__kids:
ref_coords = self.__kids[ref_name].get_ref_coords()
cur_coords = self.__kids[ref_name].get_cur_coords()
sc1 = sc2 = None
if ref_coords is not None:
ccr = sppasCoordsCompare(ref_coords, coords)
sc1 = ccr.compare_coords()
if cur_coords is not None:
ccr = sppasCoordsCompare(cur_coords, coords)
sc2 = ccr.compare_coords()
if sc1 is None or sc2 is None:
if sc1 is None:
sc = sc2
else:
sc = sc1
else:
sc = 0.4 * sc1 + 0.6 * sc2
if sc is None:
sc = 0.0
scores[ref_name] = sc
scores = collections.Counter(scores)
sorted_scores = scores.most_common()
if sorted_scores[0][1] > self.__score_level:
return sorted_scores[0]
return (None, 0.0)
train_recognizer
Train the recognizer from the current set of images of known ids.
View Source
def train_recognizer(self):
"""Train the recognizer from the current set of images of known ids.
"""
images = list()
labels = list()
for i, kid in enumerate(self.__kids):
for img in self.__kids[kid]:
gray = cv2.cvtColor(img.iresize(160, 160), cv2.COLOR_BGR2GRAY)
images.append(gray)
labels.append(i)
img = self.__kids[kid].get_ref_image()
gray = cv2.cvtColor(img.iresize(160, 160), cv2.COLOR_BGR2GRAY)
images.append(gray)
labels.append(len(images))
try:
self.__recognizer = cv2.face.LBPHFaceRecognizer_create()
except AttributeError as e:
raise Exception('Error with OpenCV. You probably need to uninstall opencv-python, and/or to re-install opencv-contrib-python: {:s}'.format(str(e)))
self.__recognizer.train(images, numpy.array(labels))
predict_recognizer
Compare the given image to the existing ones.
Parameters
Returns
- tuple(kid, score) or (None, 0.)
View Source
def predict_recognizer(self, image):
"""Compare the given image to the existing ones.
:param image: (sppasImage)
:return: tuple(kid, score) or (None, 0.)
"""
if image.shape == () or image.width * image.height == 0:
logging.error('Invalid image to predict a face with the recognizer.')
return (None, 0)
if self.__recognizer is not None:
resized = image.iresize(160, 160)
gray_img = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
kidx, dist = self.__recognizer.predict(gray_img)
for i, kid in enumerate(self.__kids):
if i == kidx:
confidence = 1.0 - float(dist) / 100.0
if confidence > self.__score_level:
return (kid, confidence)
else:
return (None, 0.0)
return (None, 0.0)
write
Save the images of the known identities to the given folder.
Parameters
- folder: Place to save images
View Source
def write(self, folder):
"""Save the images of the known identities to the given folder.
:param folder: Place to save images
"""
if os.path.exists(folder) is True:
logging.warning('Folder {:s} is already existing. It is moved into the Trash of SPPAS.'.format(folder))
try:
sppasTrash().put_folder_into(folder)
except PermissionError:
logging.error("Access denied. The folder can't be deleted.")
if os.path.exists(folder) is False:
os.mkdir(folder)
for kid in self.__kids:
for i, image in enumerate(self.__kids[kid]):
filename = '{:s}_{:02d}.png'.format(kid, i)
image.write(os.path.join(folder, filename))
img = self.__kids[kid].get_ref_image()
filename = '{:s}_ref.png'.format(kid)
img.write(os.path.join(folder, filename))