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))