private void computeDescriptor(SurfFeature desc) { int index = 0; int indexGrid = 0; double sumSq = 0; for (int gy = 0; gy < gridWidth; gy++) { for (int gx = 0; gx < gridWidth; gx++, indexGrid++) { for (int hist = 0; hist < numHistBins; hist++) { double v = desc.value[index++] = histograms[indexGrid][hist]; sumSq += v * v; } } } // System.out.println("descriptor"); double norm = Math.sqrt(sumSq); for (int i = 0; i < desc.size(); i++) { desc.value[i] /= norm; } // cap values at 0.2 and re-normalize sumSq = 0; for (int i = 0; i < desc.size(); i++) { double v = desc.value[i]; if (v > 0.2) v = desc.value[i] = 0.2; sumSq += v * v; } norm = Math.sqrt(sumSq); for (int i = 0; i < desc.size(); i++) { desc.value[i] /= norm; } }
/** * Processes the image and extracts SIFT features * * @param input input image */ public void process(ImageFloat32 input) { features.reset(); featureScales.reset(); featureAngles.reset(); location.reset(); ss.constructPyramid(input); ss.computeFeatureIntensity(); ss.computeDerivatives(); detector.process(ss); orientation.setScaleSpace(ss); describe.setScaleSpace(ss); FastQueue<ScalePoint> found = detector.getFoundPoints(); for (int i = 0; i < found.size; i++) { ScalePoint sp = found.data[i]; orientation.process(sp.x, sp.y, sp.scale); GrowQueue_F64 angles = orientation.getOrientations(); int imageIndex = orientation.getImageIndex(); double pixelScale = orientation.getPixelScale(); for (int j = 0; j < angles.size; j++) { SurfFeature desc = features.grow(); double yaw = angles.data[j]; describe.process(sp.x, sp.y, sp.scale, yaw, imageIndex, pixelScale, desc); desc.laplacianPositive = sp.white; featureScales.push(sp.scale); featureAngles.push(yaw); location.grow().set(sp.x, sp.y); } } }
public <II extends ImageSingleBand> double[][] harder(BufferedImage image) { MultiSpectral<ImageFloat32> colorImage = ConvertBufferedImage.convertFromMulti(image, null, true, ImageFloat32.class); // convert the color image to greyscale ImageFloat32 greyscaleImage = ConvertImage.average((MultiSpectral<ImageFloat32>) colorImage, null); // SURF works off of integral images Class<II> integralType = GIntegralImageOps.getIntegralType(ImageFloat32.class); // define the feature detection algorithm NonMaxSuppression extractor = FactoryFeatureExtractor.nonmax(new ConfigExtract(2, detectThreshold, 5, true)); FastHessianFeatureDetector<II> detector = new FastHessianFeatureDetector<II>(extractor, maxFeaturesPerScale, 2, 9, 4, 4); // estimate orientation OrientationIntegral<II> orientation = FactoryOrientationAlgs.sliding_ii(null, integralType); DescribePointSurf<II> descriptor = FactoryDescribePointAlgs.<II>surfStability(null, integralType); // compute the integral image of the greyscale 'image' II integralgrey = GeneralizedImageOps.createSingleBand( integralType, greyscaleImage.width, greyscaleImage.height); GIntegralImageOps.transform(greyscaleImage, integralgrey); // detect fast hessian features detector.detect(integralgrey); // === This is the point were the code starts deviating from the standard SURF! === // tell algorithms which image to process orientation.setImage(integralgrey); List<ScalePoint> points = detector.getFoundPoints(); double[][] descriptions = new double[points.size()][3 * descriptor.getDescriptionLength()]; double[] angles = new double[points.size()]; int l = 0; for (ScalePoint p : points) { orientation.setScale(p.scale); angles[l] = orientation.compute(p.x, p.y); l++; } for (int i = 0; i < 3; i++) { // check if it is actually a greyscale image, take always the 1st band! ImageFloat32 colorImageBand = null; if (colorImage.getNumBands() == 1) { colorImageBand = colorImage.getBand(0); } else { colorImageBand = colorImage.getBand(i); } // compute the integral image of the i-th band of the color 'image' II integralband = GeneralizedImageOps.createSingleBand( integralType, colorImageBand.width, colorImageBand.height); GIntegralImageOps.transform(colorImageBand, integralband); // tell algorithms which image to process // orientation.setImage(integralband); descriptor.setImage(integralband); int j = 0; for (ScalePoint p : points) { // estimate orientation // orientation.setScale(p.scale); // double angle = orientation.compute(p.x, p.y); // extract the SURF description for this region SurfFeature desc = descriptor.createDescription(); descriptor.describe(p.x, p.y, angles[j], p.scale, (TupleDesc_F64) desc); double[] banddesc = desc.getValue(); if (perBandNormalization) { banddesc = Normalization.normalizeL2(banddesc); } for (int k = 0; k < SURFLength; k++) { descriptions[j][i * SURFLength + k] = banddesc[k]; } j++; } } return descriptions; }