LDAIR.py 5.11 KB
Newer Older
1 2 3 4 5 6 7 8 9
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

import facerec2010
import bob.bio.base

from .. import utils

class LDAIR (bob.bio.base.algorithm.Algorithm):
10
  """This class defines a wrapper for the `facerec2010.baseline.lda.LRLDA` class to be used as an image :py:class:`bob.bio.base.algorithm.Algorithm`.
11

Manuel Günther's avatar
Manuel Günther committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25
  **Parameters:**

  REGION_ARGS : list
    The region arguments as taken from facerec2010.baseline.lda.CohortLDA_REGIONS

  REGION_KEYWORDS : dict
    The region keywords as taken from facerec2010.baseline.lda.CohortLDA_KEYWORDS

  multiple_model_scoring : str
    The scoring strategy if models are enrolled from several images, see :py:func:`bob.bio.base.score_fusion_strategy` for more information.

  multiple_probe_scoring : str
    The scoring strategy if a score is computed from several probe images, see :py:func:`bob.bio.base.score_fusion_strategy` for more information.
  """
26 27
  def __init__(
      self,
28 29 30 31
      REGION_ARGS = facerec2010.baseline.lda.CohortLDA_REGIONS,
      REGION_KEYWORDS = facerec2010.baseline.lda.CohortLDA_KEYWORDS,
      multiple_model_scoring = 'max', # by default, compute the maximum score between several models and the probe
      multiple_probe_scoring = 'max'  # by default, compute the maximum score between the model and several probes
32 33 34 35 36 37 38 39 40 41 42
  ):
    bob.bio.base.algorithm.Algorithm.__init__(self, multiple_model_scoring=multiple_model_scoring, multiple_probe_scoring=multiple_probe_scoring, **REGION_KEYWORDS)
    self.ldair = facerec2010.baseline.lda.LRLDA(REGION_ARGS, **REGION_KEYWORDS)
    self.use_cohort = 'cohort_adjust' not in REGION_ARGS[0] or REGION_ARGS[0]['cohort_adjust']


  def _check_feature(self, feature):
    """Checks that the features are of the desired data type."""
    assert isinstance(feature, facerec2010.baseline.common.FaceRecord)
    assert hasattr(feature, "features")

Manuel Günther's avatar
Manuel Günther committed
43

44 45 46
  def load_projector(self, projector_file):
    """This function loads the Projector from the given projector file.
    This is only required when the cohort adjustment is enabled.
Manuel Günther's avatar
Manuel Günther committed
47 48 49 50 51 52

    **Parameters:**

    projector_file : str
      The name of the projector file.
      The file is actually not used, but instead we load the extractor file, which needs to be in the same directory, and must be called "Extractor.hdf5"
53 54 55 56 57 58 59 60 61 62
    """
    # To avoid re-training the Projector, we load the Extractor file instead.
    # This is only required when the cohort adjustment is enabled, otherwise the default parametrization of LDA-IR should be sufficient.
    # Be careful, THIS IS A HACK and it might not work in all circumstances!
    if self.use_cohort:
      extractor_file = projector_file.replace("Projector", "Extractor")
      self.ldair = utils.load_pickle(extractor_file)


  def enroll(self, enroll_features):
Manuel Günther's avatar
Manuel Günther committed
63 64 65 66 67 68
    """enroll(enroll_features) -> model

    Enrolls a model from features from several images by simply storing all given features.

    **Parameters:**

69
    enroll_features : [`facerec2010.baseline.common.FaceRecord`]
Manuel Günther's avatar
Manuel Günther committed
70 71 72 73
      The features used to enroll the model.

    **Returns:**

74
    model : [`facerec2010.baseline.common.FaceRecord`]
Manuel Günther's avatar
Manuel Günther committed
75 76
      The model, which is identical to the ``enroll_features``.
    """
77 78 79 80 81
    [self._check_feature(f) for f in enroll_features]
    # just store all features (should be of type FaceRecord)
    # since the given features are already in the desired format, there is nothing to do.
    return enroll_features

Manuel Günther's avatar
Manuel Günther committed
82

83
  def write_model(self, model, model_file):
Manuel Günther's avatar
Manuel Günther committed
84 85 86 87
    """Saves the enrolled model to file using the :py:func:`bob.bio.csu.save_pickle` function.

    **Parameters:**

88
    model : [`facerec2010.baseline.common.FaceRecord`]
Manuel Günther's avatar
Manuel Günther committed
89 90 91 92 93
      The model to be written.

    model_file : str
      The name of the model file that is written.
    """
94 95 96
    # just dump the model to .pkl file
    utils.save_pickle(model, model_file)

Manuel Günther's avatar
Manuel Günther committed
97

98
  def read_model(self, model_file):
Manuel Günther's avatar
Manuel Günther committed
99 100 101 102 103 104 105 106 107 108 109
    """read_model(model_file) -> model

    Loads an enrolled model from file using the :py:func:`bob.bio.csu.load_pickle` function.

    **Parameters:**

    model_file : str
      The name of the model file to be read.

    **Returns:**

110
    model : [`facerec2010.baseline.common.FaceRecord`]
Manuel Günther's avatar
Manuel Günther committed
111 112
      The model read from file.
    """
113 114 115 116 117 118 119
    # just read the model from .pkl file
    return utils.load_pickle(model_file)

  # probe and model are identically stored in a .pkl file
  read_probe = read_model

  def score(self, model, probe):
Manuel Günther's avatar
Manuel Günther committed
120 121 122 123 124 125
    """score(model, probe) -> score

    Compute the score for the given model (a list of FaceRecords) and a probe (a FaceRecord).

    **Parameters:**

126
    model : [`facerec2010.baseline.common.FaceRecord`]
Manuel Günther's avatar
Manuel Günther committed
127 128
      The model to compare, which is actually a list of extracted features.

129
    probe : `facerec2010.baseline.common.FaceRecord`
Manuel Günther's avatar
Manuel Günther committed
130 131 132 133 134 135 136
      The probe to compare.

    **Returns**:

    score : float
      A score that was fused using the fusion function defined in the constructor of this class.
    """
137 138 139 140 141 142 143 144
    if isinstance(model, list):
      # compute score fusion strategy with several model features (which is implemented in the base class)
      return self.score_for_multiple_models(model, probe)
    else:
      self._check_feature(model)
      self._check_feature(probe)

      return self.ldair.similarityMatrix([probe], [model])[0,0]