public static CascadeClassifier Load(string filename) { XmlDocument doc = new XmlDocument(); doc.Load(filename); XmlNode cascadeNode = doc.SelectSingleNode("CascadeClassifier"); int width = int.Parse(cascadeNode.Attributes["Width"].Value); int height = int.Parse(cascadeNode.Attributes["Height"].Value); int stageCount = int.Parse(cascadeNode.Attributes["StageCount"].Value); //XmlNodeList stageList = doc.SelectNodes("Stage"); StageClassifier[] classifiers = new StageClassifier[stageCount]; for (int i = 0; i < stageCount; i++) { XmlNode stageNode = cascadeNode.ChildNodes[i]; string numStr = (i + 1).ToString(); if (false == numStr.Equals(stageNode.Attributes["StageNum"].Value)) { throw new Exception("Xml文件损坏"); } classifiers[i] = LoadStageClassifier(i + 1, stageNode); } CascadeClassifier cascade = new CascadeClassifier(); cascade.LoadFrom(new Size(width, height), classifiers); return(cascade); }
/// <summary> /// 计算强分类器的阈值 /// </summary> // private void CalcThreshold() // { // MyFloat sum = 0; // foreach (WeakClassifier weak in _classifiers) // { // sum += weak.Weight; // } // sum /= 2; // _threshold = sum; // } /// <summary> /// 调整强分类器的阈值,使得检测率满足要求 /// </summary> /// <param name="result"></param> /// <param name="targetHitRate"></param> // private void AdjustThreshold(PredictResult result,MyFloat targetHitRate) // { // _trainPredictValues.Sort(); // int targetHitCount = (int)(result.Count * targetHitRate + 0.5f); // int currentHitCount = (int)(result.Count * result.HitRate); // int diff = targetHitCount - currentHitCount; // int newIndex = BinarySearch(_trainPredictValues, _threshold)-diff; // if (newIndex < 0) // newIndex = 0; // else if (newIndex >= _trainPredictValues.Count) // newIndex = _trainPredictValues.Count - 1; // _threshold = _trainPredictValues[newIndex]; // // } /// <summary> /// 二分查找,找到大于等于key且序号最小的元素 /// </summary> /// <param name="arr"></param> /// <param name="key">待查找的数值</param> /// <returns>找到的序号</returns> // int BinarySearch(List<MyFloat> arr, MyFloat key) // { // int low = 0, high = arr.Count - 1; // int mid = (low + high) / 2; // // while (low <= high) // { // mid = (high + low) / 2; // if (arr[mid] == key) // { // break; // } // else if (arr[mid] < key) // { // low = mid + 1; // } // else // { // high = mid - 1; // } // } // while (mid > 0 && arr[mid - 1] == key) // mid--; // if (arr[mid] < key && mid + 1 < arr.Count && arr[mid + 1] > key) // mid++; // return mid; // } internal static StageClassifier Load(int id, double threshold, WeakClassifier[] weaks) { StageClassifier stage = new StageClassifier(); stage._id = id; stage._threshold = threshold; stage._classifiers = weaks; return(stage); }
private static StageClassifier LoadStageClassifier(int id, XmlNode stageNode) { MyFloat threshold = MyFloat.Parse(stageNode.Attributes["Threshold"].Value); int weakNum = int.Parse(stageNode.Attributes["ClassifiersNum"].Value); WeakClassifier[] weaks = new WeakClassifier[weakNum]; for (int i = 0; i < weakNum; i++) { XmlNode weakNode = stageNode.ChildNodes[i]; weaks[i] = LoadWeakClassifier(weakNode); } StageClassifier stage = StageClassifier.Load(id, threshold, weaks); return(stage); }
public void Train(SampleCollection posSamples, SampleCollection allNegSamples, SampleCollection validateSamples, Size size, double targetFalsePositiveRate, double maxFalsePositiveRate, double minHitRate) { const int startCapacity = 20; _size = size; List <StageClassifier> stageClassifier = new List <StageClassifier>(startCapacity); double hitRate = 1; double falsePositiveRate = 1; int stageCount = 0; int maxSampleNum; SampleCollection negSamples; { //计算使用的负样本数量 double MaxMemoryUse = MemoryInfo.GetFreePhysicalMemory() - 400e6; if (MaxMemoryUse < 0) { MaxMemoryUse = 1.8e9; } //MaxMemoryUse = 2.48e9; //按照内存大小来选取负样本,在充分利用内存的同时防止使用虚拟内存 int weakNum = WeakClassifierManager.Instance.WeakClassifiers.Length; maxSampleNum = (int)(( MaxMemoryUse - 1.5e6f //预留150M给程序其它部分 ) / weakNum / sizeof(MyFloat)) - posSamples.Count; if (DebugMsg.Debug) { string msg = string.Format("\r\n单次使用负样本:{0},特征数量:{1},预计消耗内存:{2}M\r\n", maxSampleNum, weakNum, MaxMemoryUse / 1024 / 1024); DebugMsg.AddMessage(msg, 0); } } //如果已有分类器,计算当前的性能 if (_classifiers != null && _classifiers.Length > 0) { PredictResult result = EvaluateErrorRate(validateSamples); hitRate = result.HitRate; falsePositiveRate = result.FalsePositiveRate; stageCount = _classifiers.Length; stageClassifier.AddRange(_classifiers); negSamples = CreateNextSamples(allNegSamples, falsePositiveRate, maxSampleNum); if (DebugMsg.Debug) { string msg = string.Format("载入分类器完成,层数:{0},当前性能为:\r\n检测率:\t{1:P5},\t误检率:\t{2:P5}\r\n------\r\n", stageCount, hitRate, falsePositiveRate); DebugMsg.AddMessage(msg, 0); } } else { negSamples = allNegSamples.GetNegSamples(maxSampleNum); } while (falsePositiveRate > targetFalsePositiveRate && negSamples.Count != 0 && posSamples.Count != 0) { stageCount++; if (DebugMsg.Debug) { string msg = string.Format("--------------------\r\n开始训练第{0}级分类器,使用的数量为:\r\n正样本:\t{1}\t负样本:\t{2}\r\n目标检测率:\t{3:P5}\t目标误检率:\t{4:P5}\r\n", stageCount, posSamples.Count, negSamples.Count, minHitRate, maxFalsePositiveRate); DebugMsg.AddMessage(msg, 0); } StageClassifier currentStage = new StageClassifier(stageCount); PredictResult result = currentStage.Train(posSamples, negSamples, validateSamples, maxFalsePositiveRate, minHitRate); falsePositiveRate *= result.FalsePositiveRate; hitRate *= result.HitRate; stageClassifier.Add(currentStage); _classifiers = stageClassifier.ToArray(); if (DebugMsg.Debug) { string msg = string.Format("------\r\n第{0}级分类器训练结束,当前性能为:\r\n检测率:\t{1:P5},\t误检率:\t{2:P5}\r\n弱分类器数量:{3}\r\n目前训练时间总计:{4}\r\n", stageCount, hitRate, falsePositiveRate, currentStage.WeakClassifierCount, DebugMsg.stopwatch.Elapsed.ToString()); DebugMsg.AddMessage(msg, 0); } if (falsePositiveRate > targetFalsePositiveRate) { //posSamples = this.CreateNextSamples(posSamples); validateSamples = this.GetPositivePredictedSamples(validateSamples); negSamples = CreateNextSamples(allNegSamples, falsePositiveRate, maxSampleNum); } this.Save(string.Format(@"D:\ccc{0}.xml", stageCount.ToString())); } if (DebugMsg.Debug) { DebugMsg.stopwatch.Stop(); string msg = string.Format("\r\n--------------------\r\n全部训练完成,训练时间总计:{0}\r\n", DebugMsg.stopwatch.Elapsed.ToString()); DebugMsg.AddMessage(msg, 0); } this.Save(@"D:\ccc.xml"); }