public void AddClassifier(StrongClassifier classifier) { if (classifier.WeakClassifiers.Count == 0) { throw new ArgumentException("Classifier cannot have 0 features", nameof(classifier.WeakClassifiers)); } Classifiers.Add(classifier); }
/// <summary> /// Viola Jones Cascade Classifier Training Method /// </summary> /// <param name="features">Haar-Features</param> /// <param name="images">Image data</param> /// <param name="results">Results data</param> /// <param name="f">Maximum false positive rate</param> /// <param name="d">Minimum detection rate</param> /// <param name="fTarget">Target overall false positive rate</param> public void Train(List <WeakClassifier> features, double[][,] images, bool[] results, double f, double d, double fTarget, double[][,] validImages, bool[] validResults) { Classifiers = new List <StrongClassifier>(); var imagesCpy = images.Clone() as double[][, ]; // copy not to damage original images var resultsCpy = results.Clone() as bool[]; // copy not to damage original results var integralValidImages = IntegrateImages(validImages); var falsePositiveRates = new List <double>(); falsePositiveRates.Add(1.0); var detectionRates = new List <double>(); detectionRates.Add(1.0); var i = 0; Console.WriteLine("*********Traning of the cascade classifier started*********"); // Train Cascade Classifier while (falsePositiveRates[i] > fTarget) { // Strong classifiers counter i++; // WeakClassifiers counter var n = 0; falsePositiveRates.Add(falsePositiveRates.Last()); detectionRates.Add(0.0); // Train Strong Classifier var sc = new StrongClassifier(); while (falsePositiveRates[i] > f * falsePositiveRates[i - 1]) { n++; Console.Write(" "); // Train Strong Classifier with n Weak Classifiers sc.AddWeakClassifier(imagesCpy, resultsCpy, features); Classifiers.Add(sc); var detectionRate = 0.0; var falsePositiveRate = 0.0; // Evaluate current cascade classifier to determine detection rate and false positives rate Evaluate(integralValidImages, validResults, out falsePositiveRate, out detectionRate); detectionRates[i] = detectionRate; falsePositiveRates[i] = falsePositiveRate; while (detectionRate < d * detectionRates[i - 1]) { // Decrease Threshold by 0.001 sc.DecreaseThreshold(); Evaluate(integralValidImages, validResults, out falsePositiveRate, out detectionRate); detectionRates[i] = detectionRate; falsePositiveRates[i] = falsePositiveRate; } Classifiers.Remove(sc); } Classifiers.Add(sc); Console.WriteLine("Strong classifier was added. Number of weak classifiers: {0} Detection Rate: {1} False Positive Rate: {2}", sc.WeakClassifiers.Count.ToString().PadRight(10), Math.Round(detectionRates[i], 4).ToString().PadRight(10), Math.Round(falsePositiveRates[i], 4).ToString().PadRight(10)); // Get images that were classified incorrectly var posImages = new List <double[, ]>(); var posResults = new List <bool>(); for (int j = 0; j < imagesCpy.Length; j++) { var classifierResult = sc.Detect(imagesCpy[j]); if (classifierResult) { posImages.Add(imagesCpy[j]); posResults.Add(resultsCpy[j]); } } imagesCpy = posImages.ToArray(); resultsCpy = posResults.ToArray(); if (falsePositiveRates[i] > fTarget) { var fDetImgs = new List <double[, ]>(); var fDetResults = new List <bool>(); for (int j = 0; j < validImages.Length; j++) { var result = Detect(validImages[j]); if (result != validResults[j] && result) { fDetImgs.Add(validImages[j]); fDetResults.Add(validResults[j]); } } var toTakeCount = new int[] { resultsCpy.Count(r => r) - resultsCpy.Count(r => !r), fDetImgs.Count }.Where(x => x >= 0).Min(); fDetImgs = fDetImgs.Take(toTakeCount).ToList(); fDetImgs.AddRange(imagesCpy); imagesCpy = fDetImgs.ToArray(); fDetResults = fDetResults.Take(toTakeCount).ToList(); fDetResults.AddRange(resultsCpy); resultsCpy = fDetResults.ToArray(); } } Console.WriteLine("*********Traning of the cascade classifier ended*********"); Statistics(images, results); }