/// <summary> /// 将ValuedBitmapCollection按照val值从小到大排序 /// </summary> /// <param name="vpCollection">vbCollection</param> /// <returns></returns> public static ValuedBitmapCollection SortValuedBitmapCollection(ValuedBitmapCollection vbCollection) { if (vbCollection == null || vbCollection.Count == 0) { return(new ValuedBitmapCollection()); } int min; for (int i = 0; i < vbCollection.Count - 1; i++) { min = i; for (int j = i + 1; j < vbCollection.Count; j++) { if (((ValuedBitmap)vbCollection[j]).Val < ((ValuedBitmap)vbCollection[min]).Val) { min = j; } } ValuedBitmap t = (ValuedBitmap)vbCollection[min]; vbCollection[min] = vbCollection[i]; vbCollection[i] = t; } return(vbCollection); }
/// <summary> /// 在有序(val值从小到大)的ValuedBitmapCollection中插入ValuedBitmap,ValuedBitmapCollection中元素的数量 /// 不能超出limitedNumber,插入成功后返回集合元素数量 /// </summary> /// <param name="vbCollection">集合</param> /// <param name="vbmp">集合元素</param> /// <param name="limitedNumer">集合元素数量上限</param> /// <returns>返回是否插入成功</returns> public static bool InsertValuedBitmap(ref ValuedBitmapCollection vbCollection, ValuedBitmap vbmp, int limitedNumer) { ValuedBitmap tmpMap = null; bool hasinserted = false; // 返回值,是否已经插入 if (vbmp == null) { return(hasinserted); } if (vbCollection == null || vbCollection.Count == 0) { vbCollection = new ValuedBitmapCollection(); vbCollection.Add(vbmp); hasinserted = true; return(hasinserted); } for (int i = 0; i < vbCollection.Count; i++) { if (vbmp.Val < vbCollection[i].Val) { // 有新元素要插入,暂时保存队列最后一个元素,由limitedNumer来决定是否加入队列末尾 tmpMap = vbCollection[vbCollection.Count - 1]; for (int j = vbCollection.Count - 1; j > i; j--) { vbCollection[j] = vbCollection[j - 1]; } vbCollection[i] = vbmp; hasinserted = true; // 队列未满,可加入末尾 if (vbCollection.Count < limitedNumer) { vbCollection.Add(tmpMap); } break; } } if (!hasinserted && vbCollection.Count < limitedNumer) { vbCollection.Add(vbmp); hasinserted = true; } return(hasinserted); }
/// <summary> /// 训练正样本 /// </summary> /// <param name="bmp">正样本位图</param> public void TrainPositive(Bitmap bmp) { Bitmap samplebmp = null; double neg_distance = 0; double pos_distance = 0; bool hasinserted = false; // 指明样本是否已插入队列 samplebmp = ImgOper.ResizeImage(bmp, Parameter.DETECT_WINDOW_SIZE.Width, Parameter.DETECT_WINDOW_SIZE.Height); samplebmp = ImgOper.Grayscale(samplebmp); for (double angle = (-1) * Parameter.ANGLE_BORDER; angle < Parameter.ANGLE_BORDER; angle += Parameter.ANGLE_INTERVAL) { Bitmap bmpclone = ImgOper.RotateImage(samplebmp, angle); bmpclone = ImgOper.ResizeImage(bmpclone, Parameter.DETECT_WINDOW_SIZE.Width, Parameter.DETECT_WINDOW_SIZE.Height); for (double scale = (-1) * Parameter.SCALE_BORDER; scale < Parameter.SCALE_BORDER; scale += Parameter.SCALE_INTERVAL) { // 往两个方向去,所以是减号 IntPoint lt = new IntPoint((int)(bmpclone.Width * scale / 2), (int)(bmpclone.Height * scale / 2)); IntPoint rt = new IntPoint(bmpclone.Width - 1 - (int)(bmpclone.Width * scale / 2), (int)(bmpclone.Height * scale / 2)); IntPoint rb = new IntPoint(bmpclone.Width - 1 - (int)(bmpclone.Width * scale / 2), bmpclone.Height - 1 - (int)(bmpclone.Height * scale / 2)); IntPoint lb = new IntPoint((int)(bmpclone.Width * scale / 2), bmpclone.Height - 1 - (int)(bmpclone.Height * scale / 2)); Bitmap scalebmp = ImgOper.QuadrilateralTransform(bmpclone, lt, rt, rb, lb); HogGram hogGram = HogGram.GetHogFromBitmap(scalebmp, Parameter.CELL_SIZE.Width, Parameter.CELL_SIZE.Height, Parameter.PART_NUMBER); NormBlockVectorGram blockGram = new NormBlockVectorGram(hogGram, Parameter.BLOCK_SIZE.Width, Parameter.BLOCK_SIZE.Height); Rectangle rect = new Rectangle(0, 0, hogGram.HogSize.Width, hogGram.HogSize.Height); double[] vect = blockGram.GetHogWindowVec(rect); if (Dimension != 0 && vect.Length != Dimension) { throw new Exception("输入正样本的尺寸与其他样本尺寸不一致!"); } ValuedBitmap vbmp = null; if (NegCenter != null && PosCenter != null) { // 计算离正负中心的距离 for (int i = 0; i < vect.Length; i++) { neg_distance += Math.Abs(vect[i] - NegCenter[i]); pos_distance += Math.Abs(vect[i] - PosCenter[i]); } // 与负样本中心重合时,说明是负样本,不能插入正样本队列 if (neg_distance == 0) { return; } // 检测到的正样本加入样本队列的第二道关,如果不够接近正样本中心,就无法加入队列 // 按照Hog检测的判定条件,正距离乘以Parameter.POS_DIST_COEF,使其避开边界 if (neg_distance < pos_distance * Parameter.POS_DIST_COEF) { return; } // 带归一化的系数,如果用pos_distance/neg_distance,值可能会溢出; // 将pos_distance / (pos_distance + neg_distance)作为正样本的评价系数,值越小越接近正样本 vbmp = new ValuedBitmap(scalebmp, pos_distance / (pos_distance + neg_distance)); } else { // 如果正或负样本库还没建立起来,则Val暂时赋值为1 vbmp = new ValuedBitmap(scalebmp, 1); } // 检测到的正样本加入样本队列的第三道关,与正样本评价系数的有序队列比较后,决定是否加入样本队列 hasinserted = InsertValuedBitmap(ref PosMapCollection, vbmp, Parameter.POS_LIMITED_NUMBER); PosLength = PosMapCollection.Count; //// 人工观察正样本插入情况 //if (hasinserted && vbmp != null) //{ // vbmp.VBitmap.Save("Image\\pos_save\\" + poscnt + "_" + vbmp.Val + ".jpg"); // poscnt++; //} // 如果样本已经插入队列,说明样本比较可信,重新计算样本中心 if (hasinserted) { if (PosCenter == null) { Dimension = vect.Length; PosCenter = new double[Dimension]; } for (int i = 0; i < Dimension; i++) { PosCenter[i] = (PosCenter[i] * PosLength + vect[i]) / (PosLength + 1); } } } } }
/// <summary> /// 训练负样本 /// </summary> /// <param name="bmp">负样本位图</param> public void TrainNegative(Bitmap bmp) { Bitmap samplebmp = null; double neg_distance = 0; double pos_distance = 0; bool hasinserted = false; // 指明样本是否已插入队列 if (bmp.Width / Parameter.DETECT_WINDOW_SIZE.Width > bmp.Height / Parameter.DETECT_WINDOW_SIZE.Height) { samplebmp = ImgOper.ResizeImage(bmp, (int)(bmp.Width * Parameter.DETECT_WINDOW_SIZE.Height / bmp.Height), Parameter.DETECT_WINDOW_SIZE.Height); } else { samplebmp = ImgOper.ResizeImage(bmp, Parameter.DETECT_WINDOW_SIZE.Width, (int)(bmp.Height * Parameter.DETECT_WINDOW_SIZE.Width / bmp.Width)); } samplebmp = ImgOper.CutImage(samplebmp, 0, 0, Parameter.DETECT_WINDOW_SIZE.Width, Parameter.DETECT_WINDOW_SIZE.Height); samplebmp = ImgOper.Grayscale(samplebmp); HogGram hogGram = HogGram.GetHogFromBitmap(samplebmp, Parameter.CELL_SIZE.Width, Parameter.CELL_SIZE.Height, Parameter.PART_NUMBER); NormBlockVectorGram blockGram = new NormBlockVectorGram(hogGram, Parameter.BLOCK_SIZE.Width, Parameter.BLOCK_SIZE.Height); Rectangle rect = new Rectangle(0, 0, hogGram.HogSize.Width, hogGram.HogSize.Height); double[] vect = blockGram.GetHogWindowVec(rect); if (Dimension != 0 && vect.Length != Dimension) { throw new Exception("输入负样本的尺寸与其他样本尺寸不一致!"); } ValuedBitmap vbmp = null; if (PosCenter != null && NegCenter != null) { // 计算离正负中心的距离 for (int i = 0; i < vect.Length; i++) { neg_distance += Math.Abs(vect[i] - NegCenter[i]); pos_distance += Math.Abs(vect[i] - PosCenter[i]); } // 与正样本中心重合时,说明是正样本,不能插入负样本队列 if (pos_distance == 0) { return; } // 负样本加入样本队列的第二道关,如果不够接近负样本中心,就无法加入队列 // 按照Hog检测的判定条件,正距离乘以Parameter.POS_DIST_COEF,使其避开边界 if (pos_distance * Parameter.POS_DIST_COEF < neg_distance) { return; } // 带归一化的系数,如果用neg_distance / pos_distance,值可能会溢出; // 将neg_distance / (pos_distance + neg_distance)作为负样本的评价系数,值越小越接近负样本 vbmp = new ValuedBitmap(samplebmp, neg_distance / (pos_distance + neg_distance)); } else { // 如果正样本库还没建立起来,则Val暂时赋值为1 vbmp = new ValuedBitmap(samplebmp, 1); } // 负样本加入样本队列的第三道关,与负样本评价系数的有序队列比较后,决定是否加入样本队列 hasinserted = InsertValuedBitmap(ref NegMapCollection, vbmp, Parameter.NEG_LIMITED_NUMBER); NegLength = NegMapCollection.Count; //// 人工观察负样本插入情况 //if (hasinserted && vbmp != null) //{ // vbmp.VBitmap.Save("Image\\neg_save\\" + negcnt + "_" + vbmp.Val + ".jpg"); // negcnt++; //} // 如果样本已经插入队列,说明样本比较可信,重新计算样本中心 if (hasinserted) { if (NegCenter == null) { Dimension = vect.Length; NegCenter = new double[Dimension]; } for (int i = 0; i < Dimension; i++) { NegCenter[i] = (NegCenter[i] * NegLength + vect[i]) / (NegLength + 1); } } }
/// <summary> /// 集合中增加Bitmap /// </summary> /// <param name="bmp"></param> public void Remove(ValuedBitmap bmp) { base.Remove(bmp); }
/// <summary> /// 集合中添加Bitmap /// </summary> /// <param name="bmp"></param> public void Add(ValuedBitmap bmp) { base.Add(bmp); }