/// <summary> /// 取得一个样本的特征 /// </summary> /// <param name="bmpSource">源图像,需24位或32位真彩位图</param> /// <param name="template">基础分类器模板</param> /// <param name="sampletype">样本类型,1表示正样本,-1表示负样本</param> /// <returns>返回一个样本的特征</returns> public static SampleFeature GetSampleFeature(Bitmap bmpSource, BaseClassifierTemplate template, int sampletype) { SampleFeature sf = null; Bitmap bmp = bmpSource; if (bmp != null && (bmp.PixelFormat == PixelFormat.Format24bppRgb || bmp.PixelFormat == PixelFormat.Format32bppRgb || bmp.PixelFormat == PixelFormat.Format32bppArgb)) { // 将图像调整至模板大小 if (bmp.Width != template.BmpWidth || bmp.Height != template.BmpHeight) { bmp = ImgOper.ResizeImage(bmpSource, template.BmpWidth, template.BmpHeight); } bmp = ImgOper.Grayscale(bmpSource); int[,] igram = ImgOper.Integrogram(bmp, 1); sf = new SampleFeature(); sf.GroupNum = template.GroupNum; sf.FeatureNum = template.FeatureNum; sf.SampleType = sampletype; sf.FeatureValue = BaseClassifierTemplate.GetFeatureCodeGroup(igram, bmp.Width, bmp.Height, template, 0, 0); } return(sf); }
/// <summary> /// 用模板去检测图像中的物体 /// </summary> /// <param name="bmpSource">源图像,需24位或32位真彩位图</param> /// <param name="template">基础分类器模板</param> /// <param name="fern">Fern</param> /// <returns></returns> public static RectangleCollection DetectObject(Bitmap bmpSource, BaseClassifierTemplate template, Fern fern) { RectangleCollection rc = new RectangleCollection(); Bitmap bmp = bmpSource; if (bmpSource.Width < template.BmpWidth || bmpSource.Height < template.BmpHeight) { return(null); } if (bmp != null && (bmp.PixelFormat == PixelFormat.Format24bppRgb || bmp.PixelFormat == PixelFormat.Format32bppRgb || bmp.PixelFormat == PixelFormat.Format32bppArgb)) { UInt32[] featurecode = null; bmp = ImgOper.Grayscale(bmpSource); int[,] igram = ImgOper.Integrogram(bmp, 1); while (template.BmpWidth < bmp.Width && template.BmpHeight < bmp.Height) { for (int y = 0; y < bmp.Height - template.BmpHeight + 1; y += (template.BmpHeight / 10)) { for (int x = 0; x < bmp.Width - template.BmpWidth + 1; x += (template.BmpWidth / 10)) { //int posnum = 0; //int negnum = 0; featurecode = BaseClassifierTemplate.GetFeatureCodeGroup(igram, bmp.Width, bmp.Height, template, x, y); double prob = 0; for (int i = 0; i < template.GroupNum; i++) { prob += fern.Probability[featurecode[i]]; //prob = fern.Probability[featurecode[i]]; //if (prob > 0.5) //{ // posnum++; //} //else //{ // negnum++; //} } prob = prob / template.GroupNum; if (prob > 0.5) //if (posnum > negnum) { Rectangle rect = new Rectangle(x, y, template.BmpWidth, template.BmpHeight); rc.Add(rect); } } } template.ResizeTemplate(1.2); } } return(rc); }
/// <summary> /// 直接计算两幅灰度图的相关系数 /// </summary> /// <param name="bmpX"></param> /// <param name="bmpY"></param> /// <returns></returns> public static double ComputeAssociationCoef(Bitmap bmpX, Bitmap bmpY) { int[,] igramX1 = null; //第一幅图像的标准积分图 int[,] igramX2 = null; //第一幅图像的平方积分图 int[,] igramY1 = null; //第二幅图像的标准积分图 int[,] igramY2 = null; //第二幅图像的平方积分图 int[,] igramXY1 = null; //两幅图像相乘积分图 if (bmpX != null && bmpX.PixelFormat == PixelFormat.Format8bppIndexed && bmpY != null && bmpY.PixelFormat == PixelFormat.Format8bppIndexed && bmpX.Width == bmpY.Width && bmpX.Height == bmpY.Height) { Rectangle rect = new Rectangle(0, 0, bmpX.Width, bmpY.Height); igramX1 = ImgOper.Integrogram(bmpX, 1); igramX2 = ImgOper.Integrogram(bmpX, 2); igramY1 = ImgOper.Integrogram(bmpY, 1); igramY2 = ImgOper.Integrogram(bmpY, 2); igramXY1 = ImgOper.Integrogram(bmpX, bmpY, 1); return(ComputeAssociationCoef(igramX1, igramX2, igramY1, igramY2, igramXY1, rect)); } return(0); }
/// <summary> /// 用训练好的模型测试已标记样本的类别 /// </summary> /// <param name="sample">已标记样本图像</param> /// <param name="template">基础分类器模板</param> /// <param name="fern">Fern</param> /// <returns>返回测试结果,类别</returns> public static int DetectSample(Bitmap sample, BaseClassifierTemplate template, Fern fern) { Bitmap bmp = null; if (sample.Width != template.BmpWidth || sample.Height != template.BmpHeight) { bmp = ImgOper.ResizeImage(sample, template.BmpWidth, template.BmpHeight); } else { bmp = sample; } if (bmp != null && (bmp.PixelFormat == PixelFormat.Format24bppRgb || bmp.PixelFormat == PixelFormat.Format32bppRgb || bmp.PixelFormat == PixelFormat.Format32bppArgb)) { bmp = ImgOper.Grayscale(bmp); int[,] igram = ImgOper.Integrogram(bmp, 1); UInt32[] featurecode = BaseClassifierTemplate.GetFeatureCodeGroup(igram, bmp.Width, bmp.Height, template, 0, 0); double prob = 0; for (int i = 0; i < template.GroupNum; i++) { prob += fern.Probability[featurecode[i]]; } prob = prob / template.GroupNum; if (prob > 0.5) { return(1); } else { return(-1); } } return(0); }
/// <summary> /// 计算最近正样本距离系数,按照距离而不是相关系数,这样效率高,系数越小,检测对象越接近目标 /// </summary> /// <param name="rect">检测目标区域</param> /// <param name="bmp">整幅位图</param> /// <returns>最近距离系数, double.MaxValue表示计算异常或没计算</returns> public double MinDistance(RectangleF rect, Bitmap bmp) { double mindistance = double.MaxValue; // 返回值 double dist = double.MaxValue; double minposdist = double.MaxValue; double minnegdist = double.MaxValue; if (rect == Rectangle.Empty) { return(mindistance); } DateTime dt = DateTime.Now; double elapse = 0; Bitmap patch = ImgOper.CutImage(bmp, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height); patch = ImgOper.ResizeImage(patch, Parameter.DETECT_WINDOW_SIZE.Width, Parameter.DETECT_WINDOW_SIZE.Height); patch = ImgOper.Grayscale(patch); int[,] patchgram = ImgOper.Integrogram(patch, 1); byte[] patchdata = ImgOper.GetGraybmpData(patch); double patchmean = (double)patchgram[patch.Height - 1, patch.Width - 1] / (double)(patch.Width * patch.Height); double[] patchdatad = new double[patchdata.Length]; for (int i = 0; i < patchdata.Length; i++) { patchdatad[i] = patchdata[i] - patchmean; } foreach (ValuedBitmap posbmp in PosMapCollection) { int[,] posgram = ImgOper.Integrogram(posbmp.VBitmap, 1); byte[] posdata = ImgOper.GetGraybmpData(posbmp.VBitmap); double posmean = (double)posgram[posbmp.VBitmap.Height - 1, posbmp.VBitmap.Width - 1] / (double)(posbmp.VBitmap.Width * posbmp.VBitmap.Height); double[] posdatad = new double[posdata.Length]; for (int i = 0; i < posdata.Length; i++) { posdatad[i] = posdata[i] - posmean; } dist = ImgStatCompute.ComputeDistance(patchdatad, posdatad); if (dist < minposdist) { minposdist = dist; } } foreach (ValuedBitmap negbmp in NegMapCollection) { int[,] neggram = ImgOper.Integrogram(negbmp.VBitmap, 1); byte[] negdata = ImgOper.GetGraybmpData(negbmp.VBitmap); double negmean = (double)neggram[negbmp.VBitmap.Height - 1, negbmp.VBitmap.Width - 1] / (double)(negbmp.VBitmap.Width * negbmp.VBitmap.Height); double[] negdatad = new double[negdata.Length]; for (int i = 0; i < negdata.Length; i++) { negdatad[i] = negdata[i] - negmean; } dist = ImgStatCompute.ComputeDistance(patchdatad, negdatad); if (dist < minnegdist) { minnegdist = dist; } } if (minnegdist != 0 || minposdist != 0) { // 带归一化的系数,如果用minposdist/minnegdist,值可能会溢出 mindistance = minposdist / (minposdist + minnegdist); } elapse = DateTime.Now.Subtract(dt).TotalMilliseconds; return(mindistance); }