/// <summary> /// Given a specific image, eliminate the redunant features (i.e. remove any feature that is outside the green circle /// </summary> /// <param name="reps">current template pyrimid to be checked</param> /// <param name="image">the video image, served as a size comparator</param> /// /// <returns>nothing.</returns> public static TemplatePyramid validateFeatures(TemplatePyramid reps, Gray <byte>[,] image) { List <Feature> temp; int shortSide = (image.Width() < image.Height()) ? image.Width() : image.Height(); foreach (Template t in reps.Templates) { temp = t.Features.ToList(); for (int i = 0; i < t.Features.Count(); i++) { int p = (t.Features[i].X + t.BoundingRect.X - image.Width() / 2) * (t.Features[i].X + t.BoundingRect.X - image.Width() / 2) + (t.Features[i].Y + t.BoundingRect.Y - image.Height() / 2) * (t.Features[i].Y + t.BoundingRect.Y - image.Height() / 2); //Console.WriteLine(p + " " + t.Features[i].X + " " + t.Features[i].Y); if (p > ((shortSide / 2) * (shortSide / 2))) { //Console.WriteLine(p + "asdf gsfdgafhsdgsdfhsdhsdhsd " + t.Features[i].X + " " + t.Features[i].Y); temp.Remove(t.Features[i]); } } t.Features = temp.ToArray(); //Console.WriteLine("NUM of features: " + t.Features.Count()); //GC.Collect(); } return(reps); }
private static Gray <byte>[,] QuantizeOrientations(Gray <int>[,] orientDegImg) { var quantizedUnfilteredOrient = new Gray <byte> [orientDegImg.Height(), orientDegImg.Width()]; using (var uOrientDegImg = orientDegImg.Lock()) using (var uQuantizedUnfilteredOrient = quantizedUnfilteredOrient.Lock()) { int * orientDegImgPtr = (int *)uOrientDegImg.ImageData; byte *qOrinetUnfilteredPtr = (byte *)uQuantizedUnfilteredOrient.ImageData; int qOrinetUnfilteredStride = uQuantizedUnfilteredOrient.Stride; int imgWidth = uOrientDegImg.Width; int imgHeight = uOrientDegImg.Height; for (int j = 0; j < imgHeight; j++) { for (int i = 0; i < imgWidth; i++) { int angle = orientDegImgPtr[i]; qOrinetUnfilteredPtr[i] = AngleQuantizationTable[angle]; //[0-360] -> [...] -> [0-7] (for mapping see "CalculateAngleQuantizationTable()") } orientDegImgPtr += imgWidth; //<Gray<int>> is always alligned qOrinetUnfilteredPtr += qOrinetUnfilteredStride; } } //quantizedUnfilteredOrient.Mul(36).Save("quantizedUnfilteredImg.bmp"); return(quantizedUnfilteredOrient); }
/// <summary> /// build template List from a Gray image /// </summary> /// <param name="image">input image</param> /// <param name="buildXMLTemplateFile">true to build a xml file with current templates</param> /// <param name="angles">the number of angles, default to 360</param> /// <param name="sizes">number of sizes, default to 1</param> /// <param name="minRatio">The ratio of smallest size to original, default to 0.6</param> /// <param name="maxFeaturesPerLevel">the array of maximum features per pyrimid level, default to 200 in DEFAULT_MAX_FEATURES_PER_LEVEL from ImageTemplatePyramid.cs:56, /// increase to increase the precision in expense of detection time-delay</param> /// <param name="userFunc">Input User Function for customization and diversity</param> /// <returns>List of templates.</returns> public static List <TemplatePyramid> buildTemplate(Gray <byte>[,] image, int Width, int Height, bool buildXMLTemplateFile = false, int angles = 360, int sizes = 1, float minRatio = 0.6f, int[] maxFeaturesPerLevel = null, Func <TemplatePyramid, Gray <byte> [, ], TemplatePyramid> userFunc = null) { List <TemplatePyramid> retList = new List <TemplatePyramid>(); float Ratio = 1; Gray <byte>[,] tempIMG; rotateLoad(retList, image, angles, Width, Height, false, userFunc: validateFeatures); for (int i = 0; i < sizes - 1; i++) { Ratio -= (float)(1 - minRatio) / sizes; int width = (int)(image.Width() * Ratio); int height = (int)(image.Height() * Ratio); DotImaging.Primitives2D.Size Nsize = new DotImaging.Primitives2D.Size(width, height); tempIMG = ResizeExtensions_Gray.Resize(image, Nsize, Accord.Extensions.Imaging.InterpolationMode.NearestNeighbor); rotateLoad(retList, tempIMG, angles, Width, Height, false, maxFeaturesPerLevel, image.ToString(), userFunc: userFunc); } if (buildXMLTemplateFile) { XMLTemplateSerializer <ImageTemplatePyramid <ImageTemplate>, ImageTemplate> .ToFile(retList, Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, "Resources", "template" + ".xml")); } return(retList); }
/// <summary> /// Creates linear response maps. /// </summary> /// <param name="orientationDegImg">Orientation image (in degrees).</param> /// <param name="neigborhood">Spread neighborhood size.</param> public LinearizedMaps(Gray <int>[,] orientationDegImg, int neigborhood) { this.NeigborhoodSize = neigborhood; this.ImageSize = orientationDegImg.Size(); this.LinearMapSize = new Size(orientationDegImg.Width() / neigborhood, orientationDegImg.Height() / neigborhood); this.ImageValidSize = new Size(this.LinearMapSize.Width * neigborhood, this.LinearMapSize.Height * neigborhood); this.LinearMaps = calculate(orientationDegImg); }
/// <summary> /// Computes gradient orientations from the color image. Orientation from the channel which has the maximum gradient magnitude is taken as the orientation for a location. /// </summary> /// <param name="frame">Image.</param> /// <param name="magnitudeSqrImage">Squared magnitude image.</param> /// <param name="minValidMagnitude">Minimal valid magnitude.</param> /// <returns>Orientation image (angles are in degrees).</returns> public unsafe static Gray <int>[,] Compute(Gray <byte>[,] frame, out Gray <int>[,] magnitudeSqrImage, int minValidMagnitude) { var minSqrMagnitude = minValidMagnitude * minValidMagnitude; var orientationImage = new Gray <int> [frame.Height(), frame.Width()]; var _magnitudeSqrImage = orientationImage.CopyBlank(); using (var uFrame = frame.Lock()) { ParallelLauncher.Launch(thread => { computeGray(thread, (byte *)uFrame.ImageData, uFrame.Stride, orientationImage, _magnitudeSqrImage, minSqrMagnitude); }, frame.Width() - 2 * kernelRadius, frame.Height() - 2 * kernelRadius); } magnitudeSqrImage = _magnitudeSqrImage; return(orientationImage); }
/// <summary> /// rotate the image for <param name="angles"> angles and load them into the <param name="retList"> List. /// </summary> /// <param name="retList">the list that mean to be loaded with the new templates, create a new one if null is passed in</param> /// <param name="image">input image</param> /// <param name="angles">the number of angles</param> /// <param name="Width">The Width that the orginal image is cropped into, must be less than image.Width()</param> /// <param name="Height">The Height that the orginal image is cropped into, must be less than image.Height()</param> /// <param name="buildXMLTemplateFile">true to build a xml file with current templates</param> /// <param name="maxFeaturesPerLevel">the array of maximum features per pyrimid level, default to 200 in DEFAULT_MAX_FEATURES_PER_LEVEL from ImageTemplatePyramid.cs:56, /// increase to increase the precision in expense of detection time-delay</param> /// <param name="userFunc">Input User Function for customization and diversity</param> /// <returns>nothing.</returns> private static void rotateLoad(List <TemplatePyramid> retList, Gray <byte>[,] image, int angles, int Width, int Height, bool buildXMLTemplateFile = false, int[] maxFeaturesPerLevel = null, string name = "DefaultTemplate", Func <TemplatePyramid, Gray <byte> [, ], TemplatePyramid> userFunc = null) { string resourceDir = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, "Resources"); retList = (retList == null ? new List <TemplatePyramid>() : retList); Width = (Width > image.Width() ? image.Width() : Width); Height = (Height > image.Height() ? image.Height() : Height); //userFunc = (userFunc != null) ? userFunc : (inputList, inputImage) => inputList; for (int i = 0; i < angles; i++) { float ImageAngle = (float)i * 360 / angles; Bitmap bitmap = image.ToBitmap(); Bitmap returnBitmap = new Bitmap(Width, Height); Graphics graphics = Graphics.FromImage(returnBitmap); graphics.TranslateTransform((float)Width / 2, (float)Height / 2); graphics.RotateTransform(ImageAngle); graphics.TranslateTransform(-(float)Width / 2, -(float)Height / 2); graphics.DrawImage(bitmap, new System.Drawing.Point(-(image.Width() - Width) / 2, -(image.Height() - Height) / 2)); bitmap.Dispose(); returnBitmap.Save("TP.bmp"); Console.WriteLine(" angle " + ImageAngle); Gray <byte>[,] preparedBWImage = ImageIO.LoadGray("TP.bmp").Clone(); try { TemplatePyramid newTemp = TemplatePyramid.CreatePyramidFromPreparedBWImage( preparedBWImage, name, ImageAngle, maxNumberOfFeaturesPerLevel: maxFeaturesPerLevel); if (userFunc != null) { newTemp = userFunc(newTemp, image); } retList.Add(newTemp); } catch (Exception) { } } if (buildXMLTemplateFile) { XMLTemplateSerializer <ImageTemplatePyramid <ImageTemplate>, ImageTemplate> .ToFile(retList, Path.Combine(resourceDir, "template" + ".xml")); } }
/// <summary> /// Creates integral image. /// </summary> /// <param name="img">Image.</param> /// <returns>Integral image.</returns> public static Gray <double>[,] MakeIntegral(this Gray <double>[,] img) { var dstImg = new Gray <double> [img.Height() + 1, img.Width() + 1]; using (var uImg = img.Lock()) using (var uDstImg = dstImg.Lock()) { makeIntegral_Double(uImg, uDstImg); } return(dstImg); }