/// <summary> /// Process image looking for interest points. /// </summary> /// /// <param name="image">Source image data to process.</param> /// /// <returns>Returns list of found interest points.</returns> /// public List <FastRetinaKeypoint> ProcessImage(UnmanagedImage image) { // check image format if ( (image.PixelFormat != PixelFormat.Format8bppIndexed) && (image.PixelFormat != PixelFormat.Format24bppRgb) && (image.PixelFormat != PixelFormat.Format32bppRgb) && (image.PixelFormat != PixelFormat.Format32bppArgb) ) { throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); } // make sure we have grayscale image if (image.PixelFormat == PixelFormat.Format8bppIndexed) { grayImage = image; } else { // create temporary grayscale image grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image); } // 1. Extract corners points from the image. List <IntPoint> corners = Detector.ProcessImage(grayImage); var features = new List <FastRetinaKeypoint>(); for (int i = 0; i < corners.Count; i++) { features.Add(new FastRetinaKeypoint(corners[i].X, corners[i].Y)); } // 2. Compute the integral for the given image integral = IntegralImage.FromBitmap(grayImage); // 3. Compute feature descriptors if required descriptor = null; if (featureType != FastRetinaKeypointDescriptorType.None) { descriptor = GetDescriptor(); descriptor.Compute(features); } return(features); }
/// <summary> /// This method should be implemented by inheriting classes to implement the /// actual feature extraction, transforming the input image into a list of features. /// </summary> /// protected override IEnumerable <FastRetinaKeypoint> InnerTransform(UnmanagedImage image) { // make sure we have grayscale image if (image.PixelFormat == PixelFormat.Format8bppIndexed) { grayImage = image; } else { // create temporary grayscale image grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image); } // 1. Extract corners points from the image. List <IntPoint> corners = Detector.ProcessImage(grayImage); var features = new List <FastRetinaKeypoint>(); for (int i = 0; i < corners.Count; i++) { features.Add(new FastRetinaKeypoint(corners[i].X, corners[i].Y)); } // 2. Compute the integral for the given image integral = IntegralImage.FromBitmap(grayImage); // 3. Compute feature descriptors if required descriptor = null; if (featureType != FastRetinaKeypointDescriptorType.None) { descriptor = GetDescriptor(); descriptor.Compute(features); } return(features); }
/// <summary> /// Process image looking for interest points. /// </summary> /// /// <param name="image">Source image data to process.</param> /// /// <returns>Returns list of found interest points.</returns> /// /// <exception cref="UnsupportedImageFormatException"> /// The source image has incorrect pixel format. /// </exception> /// public List <SurfPoint> ProcessImage(UnmanagedImage image) { // check image format if ( (image.PixelFormat != PixelFormat.Format8bppIndexed) && (image.PixelFormat != PixelFormat.Format24bppRgb) && (image.PixelFormat != PixelFormat.Format32bppRgb) && (image.PixelFormat != PixelFormat.Format32bppArgb) ) { throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); } // make sure we have grayscale image UnmanagedImage grayImage = null; if (image.PixelFormat == PixelFormat.Format8bppIndexed) { grayImage = image; } else { // create temporary grayscale image grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image); } // 1. Compute the integral for the given image integral = IntegralImage.FromBitmap(grayImage); // 2. Compute interest point response map if (responses == null || image.Width != responses.Width || image.Height != responses.Height) { responses = new ResponseFilters(image.Width, image.Height, octaves, initial); } responses.Compute(integral); // 3. Suppress non-maximum points List <SurfPoint> featureList = new List <SurfPoint>(); // for each image pyramid in the response map foreach (ResponseLayer[] layers in responses) { // Grab the three layers forming the pyramid ResponseLayer bot = layers[0]; // bottom layer ResponseLayer mid = layers[1]; // middle layer ResponseLayer top = layers[2]; // top layer int border = (top.Size + 1) / (2 * top.Step); int tstep = top.Step; int mstep = mid.Size - bot.Size; int mscale = mid.Width / top.Width; int bscale = bot.Width / top.Width; int r = 1; // for each row for (int y = border + 1; y < top.Height - border; y++) { // for each pixel for (int x = border + 1; x < top.Width - border; x++) { float currentValue = mid.Responses[y * mscale, x *mscale]; // for each windows' row for (int i = -r; (currentValue >= threshold) && (i <= r); i++) { // for each windows' pixel for (int j = -r; j <= r; j++) { int yi = y + i; int xj = x + j; // for each response layer if (top.Responses[yi, xj] >= currentValue || bot.Responses[yi * bscale, xj *bscale] >= currentValue || ((i != 0 || j != 0) && mid.Responses[yi * mscale, xj *mscale] >= currentValue)) { currentValue = 0; break; } } } // check if this point is really interesting if (currentValue >= threshold) { // interpolate to sub-pixel precision double[] offset = interpolate(y, x, top, mid, bot); if (System.Math.Abs(offset[0]) < 0.5 && System.Math.Abs(offset[1]) < 0.5 && System.Math.Abs(offset[2]) < 0.5) { featureList.Add(new SurfPoint( (float)((x + offset[0]) * tstep), (float)((y + offset[1]) * tstep), (float)(0.1333f * (mid.Size + offset[2] * mstep)), mid.Laplacian[y * mscale, x * mscale])); } } } } } return(featureList); }
private List <SpeededUpRobustFeaturePoint> processImage(UnmanagedImage image) { // make sure we have grayscale image UnmanagedImage grayImage = null; if (image.PixelFormat == PixelFormat.Format8bppIndexed) { grayImage = image; } else { // create temporary grayscale image grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image); } // 1. Compute the integral for the given image integral = IntegralImage.FromBitmap(grayImage); // 2. Create and compute interest point response map if (responses == null) { // re-create only if really needed responses = new ResponseLayerCollection(image.Width, image.Height, octaves, initial); } else { responses.Update(image.Width, image.Height, initial); } // Compute the response map responses.Compute(integral); // 3. Suppress non-maximum points List <SpeededUpRobustFeaturePoint> featureList = new List <SpeededUpRobustFeaturePoint>(); // for each image pyramid in the response map foreach (ResponseLayer[] layers in responses) { // Grab the three layers forming the pyramid ResponseLayer bot = layers[0]; // bottom layer ResponseLayer mid = layers[1]; // middle layer ResponseLayer top = layers[2]; // top layer int border = (top.Size + 1) / (2 * top.Step); int tstep = top.Step; int mstep = mid.Size - bot.Size; int r = 1; // for each row for (int y = border + 1; y < top.Height - border; y++) { // for each pixel for (int x = border + 1; x < top.Width - border; x++) { int mscale = mid.Width / top.Width; int bscale = bot.Width / top.Width; double currentValue = mid.Responses[y * mscale, x *mscale]; // for each windows' row for (int i = -r; (currentValue >= threshold) && (i <= r); i++) { // for each windows' pixel for (int j = -r; j <= r; j++) { int yi = y + i; int xj = x + j; // for each response layer if (top.Responses[yi, xj] >= currentValue || bot.Responses[yi * bscale, xj *bscale] >= currentValue || ((i != 0 || j != 0) && mid.Responses[yi * mscale, xj *mscale] >= currentValue)) { currentValue = 0; break; } } } // check if this point is really interesting if (currentValue >= threshold) { // interpolate to sub-pixel precision double[] offset = interpolate(y, x, top, mid, bot); if (System.Math.Abs(offset[0]) < 0.5 && System.Math.Abs(offset[1]) < 0.5 && System.Math.Abs(offset[2]) < 0.5) { featureList.Add(new SpeededUpRobustFeaturePoint( (x + offset[0]) * tstep, (y + offset[1]) * tstep, 0.133333333 * (mid.Size + offset[2] * mstep), mid.Laplacian[y * mscale, x * mscale])); } } } } } descriptor = null; if (featureType != SpeededUpRobustFeatureDescriptorType.None) { descriptor = new SpeededUpRobustFeaturesDescriptor(integral); descriptor.Extended = featureType == SpeededUpRobustFeatureDescriptorType.Extended; descriptor.Invariant = computeOrientation; descriptor.Compute(featureList); } else if (computeOrientation) { descriptor = new SpeededUpRobustFeaturesDescriptor(integral); foreach (var p in featureList) { p.Orientation = descriptor.GetOrientation(p); } } return(featureList); }