//----------------------------- For prediction -------------------------------------// /// <summary> /// Predicts the class of a unknown face using a linear discriminant. It works in the original DIM space. /// </summary> /// <param name="Face"> Face to be categorized</param> /// <returns></returns> public int PredictClassUsingDiscriminant(ATTFace Face) { double[] x = Face.ImageVectorTransformed; //We like to work on the PCA Space for classification IMatrix SigmaInv = this.SW.Inverse; int ID = -1; double maxValue = 0.0; int i = 0; foreach (KeyValuePair <int, FaceClass> entry in FacesByClass) { double[] ui = entry.Value.MeanOfClass; double pi = entry.Value.ProbabilityOfBelonging; double discriminant = Math.Abs(CalculateDiscriminantValue(x, ui, pi, SigmaInv)); Console.WriteLine("Discriminant for Class (" + entry.Value.ID + ")" + " = " + discriminant); if (i == 0) { maxValue = discriminant; } i++; if (discriminant < maxValue) { ID = entry.Value.ID; maxValue = discriminant; } } return(ID); }
private void btnTestImage_Click(object sender, EventArgs e) { if (LDAClassifier == null) { MessageBox.Show("Classifier not trained. Please press Train!"); } else { OpenFileDialog Dialog = new OpenFileDialog(); Dialog.Filter = "jpeg files (*.jpg)|*.jpg|(*.gif)|gif||"; if (DialogResult.OK == Dialog.ShowDialog()) { ATTFace face = DataUnit.GetATTFace(Dialog.FileName); double[] projectedPCA = PCAClassifier.ComputeProjection(face.ImageVector); // Do not forget to project in PCA Space face.ImageVectorTransformed = projectedPCA; Bitmap TestBitmap = face.getImagesAsBmp(); ShowImage(TestBitmap, picTestImage); FileInfo fileInfo = new FileInfo(Dialog.FileName); lblTestImage.Text = fileInfo.Name; int guessID = LDAClassifier.PredictClassInProjectedSpace(face); MessageBox.Show("Guessed Class: " + guessID); List <ATTFace> BestFaces = LDAClassifier.FacesByClass[guessID].FacesInClass; //By default, we print the images in the class DisplayBestMatches(BestFaces); } } }
public Object Clone() { ATTFace Copy = new ATTFace(); Copy.Closeness = this.Closeness; Copy.ImageVector = this.ImageVector; Copy.ImageVectorTransformed = this.ImageVectorTransformed; Copy.personID = this.personID; Copy.FileName = this.FileName; return(Copy); }
/// <summary> /// Computes the projection onto the LDABase (W) /// </summary> /// <param name="Face"></param> /// <returns></returns> private double[] ComputeLDAProjection(ATTFace Face) { double[] x = Face.ImageVectorTransformed; double[] projected = new double[WMatrix.Columns]; //C-1 Dimensions for (int j = 0; j < this.WMatrix.Columns; j++) { double temp = 0.0; for (int i = 0; i < WMatrix.Rows; i++) { temp += x[i] * WMatrix[i, j]; } projected[j] = temp; } return(projected); }
/// <summary> /// Read files and generates a training dataset /// </summary> /// <param name="trainingPath"> Directory Path of where Training data is located</param> /// <returns> </returns> public static List <ATTFace> GetTrainingData(String trainingPath) { List <ATTFace> Faces = new List <ATTFace>(); DirectoryInfo di = new DirectoryInfo(trainingPath); FileInfo[] files = di.GetFiles("*.jpg"); foreach (FileInfo fileInfo in files) { String fileName = fileInfo.Name; String[] parts = fileName.Split('_'); int personID = int.Parse(parts[0].Substring(1, parts[0].Length - 1)); Bitmap faceBitmap = new Bitmap(trainingPath + "\\" + fileName); double[] ImageAsArray = BitmapToArray(faceBitmap); ATTFace face = new ATTFace(fileName, personID, ImageAsArray); Faces.Add(face); } return(Faces); }
public int CompareTo(Object obj) { if (obj == null) { return(1); } ATTFace OtherFace = obj as ATTFace; if (OtherFace != null) { return(this.CompareTo(OtherFace.Closeness)); } else { throw new ArgumentException("Object is not an ATTFace"); } }
/// <summary> /// Allows capabilities of comparing vectors in the projected space and give an ID to the unknown data. /// </summary> /// <param name="Face"> Face to be categorized</param> /// <param name="Decision"> Decision type. Either KNN or ClossestNeighbor</param> /// <param name="neighborNumber">How many neighbors to consider if using KNN</param> /// <returns></returns> public int PredictClassInProjectedSpace(ATTFace Face, DecisionType Decision = DecisionType.ClossestNeighbor, int neighborNumber = 3) { double[] projected = ComputeLDAProjection(Face); int ID = -1; foreach (ATTFace ReferenceFace in FaceList) { double[] y = ReferenceFace.LDAProjection; double dist = EuclideanDistance(y, projected); ReferenceFace.Closeness = dist; } FaceList.Sort(); if (Decision == DecisionType.ClossestNeighbor) { ID = FaceList[0].personID; } else if (Decision == DecisionType.KNN) { IDictionary <int, int> Tally = new Dictionary <int, int>(); int maxVotes = 0; ID = -1; for (int i = 0; i < neighborNumber; i++) { ATTFace Person = FaceList[i]; if (Tally.ContainsKey(Person.personID)) { Tally[Person.personID]++; if (Tally[Person.personID] > maxVotes) { //To be here, a personID needs at leats two votes maxVotes = Tally[Person.personID]; ID = Person.personID; } } else { Tally.Add(Person.personID, 1); } } } return(ID); }
/// <summary> /// Finds the Best Match(es) as a list, and provides a guessed Person ID. /// </summary> /// <param name="imageAsVector"> Image of the person to be classified.</param> /// <param name="decisionType"> Either ClossestNeighbor or KKN</param> /// <param name="measureType"> Either Euclidean or Projection. Determines which measurement is to be used.</param> /// <param name="BestFaces"> List of ATTFaces passed by reference. Must be empty. BestMatches added to the list if onlyID = false</param> /// <param name="guessID">int passed by reference. The class of the person images guessed by PCA.</param> /// <param name="neighborNumber"> How many neighbors to use for KNN. Default is 3</param> /// <param name="numberFaces">How many Best Matches to add to BestFaces. Default is 6</param> /// <param name="onlyID"> Whether ONLY the class of the person is of interest. If the BestFaces are also of interest, set to false/</param> public void FindBestMatch(double[] imageAsVector, DecisionType decisionType, ClossenessMeasure measureType, ref List <ATTFace> BestFaces, ref int guessID, int neighborNumber = 3, int numberFaces = 6, bool onlyID = true) { double[] meanAdjusted = SubstractArrays(imageAsVector, MeanFaceAsArray); double[] projectedImage = ComputeProjection(meanAdjusted); foreach (ATTFace Person in DataSet) { double similarity; if (measureType == ClossenessMeasure.Euclidean) { similarity = EuclideanDistance(Person.ImageVectorTransformed, projectedImage); Person.Closeness = similarity; } else if (measureType == ClossenessMeasure.Projection) { similarity = DotProduct(Person.ImageVectorTransformed, projectedImage); Person.Closeness = -similarity; //A maximization is transformed to a minimization by putting a - } else { throw new ArgumentException("ClosenessMeasure is not supported!"); } } DataSet.Sort(); // ------------------------------------------ Retrieving best guess ------------------------------// if (decisionType == DecisionType.ClossestNeighbor) { guessID = DataSet[0].personID; } else if (decisionType == DecisionType.KNN) { IDictionary <int, int> Tally = new Dictionary <int, int>(); int maxVotes = 0; guessID = -1; for (int i = 0; i < neighborNumber; i++) { ATTFace Person = DataSet[i]; if (Tally.ContainsKey(Person.personID)) { Tally[Person.personID]++; if (Tally[Person.personID] > maxVotes) { //To be here, a personID needs at leats two votes maxVotes = Tally[Person.personID]; guessID = Person.personID; } } else { Tally.Add(Person.personID, 1); } } } else { throw new ArgumentException("DecisionType not valid!"); } // ---------------------------- Populating the list onlyID = False ----------------// if (!onlyID) { for (int i = 0; i < numberFaces; i++) { BestFaces.Add((ATTFace)DataSet[i].Clone()); } } }