use of georegression.struct.point.Point2D_I16 in project BoofCV by lessthanoptimal.
the class GeneralToInterestPoint method detect.
@Override
public void detect(T input) {
super.detect(input, null);
foundPoints.reset();
if (getDetector().isDetectMaximums()) {
QueueCorner corners = detector.getMaximums();
for (int i = 0; i < corners.size; i++) {
Point2D_I16 p = corners.get(i);
foundPoints.grow().set(p.x, p.y);
}
}
if (getDetector().isDetectMinimums()) {
QueueCorner corners = detector.getMinimums();
for (int i = 0; i < corners.size; i++) {
Point2D_I16 p = corners.get(i);
foundPoints.grow().set(p.x, p.y);
}
}
}
use of georegression.struct.point.Point2D_I16 in project BoofCV by lessthanoptimal.
the class FastHessianFeatureDetector method findLocalScaleSpaceMax.
/**
* Looks for features which are local maximums in the image and scale-space.
*
* @param size Size of features in different scale-spaces.
* @param level Which level in the scale-space
* @param skip How many pixels are skipped over.
*/
private void findLocalScaleSpaceMax(int[] size, int level, int skip) {
int index0 = spaceIndex;
int index1 = (spaceIndex + 1) % 3;
int index2 = (spaceIndex + 2) % 3;
ImageBorder_F32 inten0 = (ImageBorder_F32) FactoryImageBorderAlgs.value(intensity[index0], 0);
GrayF32 inten1 = intensity[index1];
ImageBorder_F32 inten2 = (ImageBorder_F32) FactoryImageBorderAlgs.value(intensity[index2], 0);
// find local maximums in image 2D space. Borders need to be ignored since
// false positives are found around them as an artifact of pixels outside being
// treated as being zero.
foundFeatures.reset();
extractor.setIgnoreBorder(size[level] / (2 * skip));
extractor.process(intensity[index1], null, null, null, foundFeatures);
// Can't consider feature which are right up against the border since they might not be a true local
// maximum when you consider the features on the other side of the ignore border
int ignoreRadius = extractor.getIgnoreBorder() + extractor.getSearchRadius();
int ignoreWidth = intensity[index1].width - ignoreRadius;
int ignoreHeight = intensity[index1].height - ignoreRadius;
// number of features which can be added
int numberRemaining;
// if configured to do so, only select the features with the highest intensity
QueueCorner features;
if (sortBest != null) {
sortBest.process(intensity[index1], foundFeatures, true);
features = sortBest.getBestCorners();
numberRemaining = maxFeaturesPerScale;
} else {
features = foundFeatures;
numberRemaining = Integer.MAX_VALUE;
}
int levelSize = size[level];
int sizeStep = levelSize - size[level - 1];
// see if these local maximums are also a maximum in scale-space
for (int i = 0; i < features.size && numberRemaining > 0; i++) {
Point2D_I16 f = features.get(i);
// avoid false positives. see above comment
if (f.x < ignoreRadius || f.x >= ignoreWidth || f.y < ignoreRadius || f.y >= ignoreHeight)
continue;
float val = inten1.get(f.x, f.y);
// see if it is a max in scale-space too
if (checkMax(inten0, val, f.x, f.y) && checkMax(inten2, val, f.x, f.y)) {
// find the feature's location to sub-pixel accuracy using a second order polynomial
// NOTE: In the original paper this was done using a quadratic. See comments above.
// NOTE: Using a 2D polynomial for x and y might produce better results.
float peakX = polyPeak(inten1.get(f.x - 1, f.y), inten1.get(f.x, f.y), inten1.get(f.x + 1, f.y));
float peakY = polyPeak(inten1.get(f.x, f.y - 1), inten1.get(f.x, f.y), inten1.get(f.x, f.y + 1));
float peakS = polyPeak(inten0.get(f.x, f.y), inten1.get(f.x, f.y), inten2.get(f.x, f.y));
float interpX = (f.x + peakX) * skip;
float interpY = (f.y + peakY) * skip;
float interpS = levelSize + peakS * sizeStep;
double scale = 1.2 * interpS / 9.0;
foundPoints.grow().set(interpX, interpY, scale);
numberRemaining--;
}
}
}
use of georegression.struct.point.Point2D_I16 in project BoofCV by lessthanoptimal.
the class FeaturePyramid method findLocalScaleSpaceMax.
/**
* Searches the pyramid layers up and down to see if the found 2D features are also scale space maximums.
*/
protected void findLocalScaleSpaceMax(PyramidFloat<T> ss, int layerID) {
int index0 = spaceIndex;
int index1 = (spaceIndex + 1) % 3;
int index2 = (spaceIndex + 2) % 3;
List<Point2D_I16> candidates = maximums[index1];
ImageBorder_F32 inten0 = (ImageBorder_F32) FactoryImageBorderAlgs.value(intensities[index0], 0);
GrayF32 inten1 = intensities[index1];
ImageBorder_F32 inten2 = (ImageBorder_F32) FactoryImageBorderAlgs.value(intensities[index2], 0);
float scale0 = (float) ss.scale[layerID - 1];
float scale1 = (float) ss.scale[layerID];
float scale2 = (float) ss.scale[layerID + 1];
float sigma0 = (float) ss.getSigma(layerID - 1);
float sigma1 = (float) ss.getSigma(layerID);
float sigma2 = (float) ss.getSigma(layerID + 1);
// not sure if this is the correct way to handle the change in scale
float ss0 = (float) (Math.pow(sigma0, scalePower) / scale0);
float ss1 = (float) (Math.pow(sigma1, scalePower) / scale1);
float ss2 = (float) (Math.pow(sigma2, scalePower) / scale2);
for (Point2D_I16 c : candidates) {
float val = ss1 * inten1.get(c.x, c.y);
// find pixel location in each image's local coordinate
int x0 = (int) (c.x * scale1 / scale0);
int y0 = (int) (c.y * scale1 / scale0);
int x2 = (int) (c.x * scale1 / scale2);
int y2 = (int) (c.y * scale1 / scale2);
if (checkMax(inten0, val / ss0, x0, y0) && checkMax(inten2, val / ss2, x2, y2)) {
// put features into the scale of the upper image
foundPoints.add(new ScalePoint(c.x * scale1, c.y * scale1, sigma1));
}
}
}
use of georegression.struct.point.Point2D_I16 in project BoofCV by lessthanoptimal.
the class FeaturePyramid method detectCandidateFeatures.
/**
* Use the feature detector to find candidate features in each level. Only compute the needed image derivatives.
*/
private void detectCandidateFeatures(T image, double sigma) {
// adjust corner intensity threshold based upon the current scale factor
float scaleThreshold = (float) (baseThreshold / Math.pow(sigma, scalePower));
detector.setThreshold(scaleThreshold);
computeDerivative.setInput(image);
D derivX = null, derivY = null;
D derivXX = null, derivYY = null, derivXY = null;
if (detector.getRequiresGradient()) {
derivX = computeDerivative.getDerivative(true);
derivY = computeDerivative.getDerivative(false);
}
if (detector.getRequiresHessian()) {
derivXX = computeDerivative.getDerivative(true, true);
derivYY = computeDerivative.getDerivative(false, false);
derivXY = computeDerivative.getDerivative(true, false);
}
detector.process(image, derivX, derivY, derivXX, derivYY, derivXY);
intensities[spaceIndex].reshape(image.width, image.height);
intensities[spaceIndex].setTo(detector.getIntensity());
List<Point2D_I16> m = maximums[spaceIndex];
m.clear();
QueueCorner q = detector.getMaximums();
for (int i = 0; i < q.size; i++) {
m.add(q.get(i).copy());
}
spaceIndex++;
if (spaceIndex >= 3)
spaceIndex = 0;
}
use of georegression.struct.point.Point2D_I16 in project BoofCV by lessthanoptimal.
the class GeneralFeatureDetector method process.
/**
* Computes point features from image gradients.
*
* @param image Original image.
* @param derivX image derivative in along the x-axis. Only needed if {@link #getRequiresGradient()} is true.
* @param derivY image derivative in along the y-axis. Only needed if {@link #getRequiresGradient()} is true.
* @param derivXX Second derivative. Only needed if {@link #getRequiresHessian()} ()} is true.
* @param derivXY Second derivative. Only needed if {@link #getRequiresHessian()} ()} is true.
* @param derivYY Second derivative. Only needed if {@link #getRequiresHessian()} ()} is true.
*/
public void process(I image, D derivX, D derivY, D derivXX, D derivYY, D derivXY) {
intensity.process(image, derivX, derivY, derivXX, derivYY, derivXY);
GrayF32 intensityImage = intensity.getIntensity();
int numSelectMin = -1;
int numSelectMax = -1;
if (maxFeatures > 0) {
if (intensity.localMinimums())
numSelectMin = excludeMinimum == null ? maxFeatures : maxFeatures - excludeMinimum.size;
if (intensity.localMaximums())
numSelectMax = excludeMaximum == null ? maxFeatures : maxFeatures - excludeMaximum.size;
// return without processing if there is no room to detect any more features
if (numSelectMin <= 0 && numSelectMax <= 0)
return;
}
// mark pixels that should be excluded
if (excludeMinimum != null) {
for (int i = 0; i < excludeMinimum.size; i++) {
Point2D_I16 p = excludeMinimum.get(i);
intensityImage.set(p.x, p.y, -Float.MAX_VALUE);
}
}
if (excludeMaximum != null) {
for (int i = 0; i < excludeMaximum.size; i++) {
Point2D_I16 p = excludeMaximum.get(i);
intensityImage.set(p.x, p.y, Float.MAX_VALUE);
}
}
foundMinimum.reset();
foundMaximum.reset();
if (intensity.hasCandidates()) {
extractor.process(intensityImage, intensity.getCandidatesMin(), intensity.getCandidatesMax(), foundMinimum, foundMaximum);
} else {
extractor.process(intensityImage, null, null, foundMinimum, foundMaximum);
}
// optionally select the most intense features only
selectBest(intensityImage, foundMinimum, numSelectMin, false);
selectBest(intensityImage, foundMaximum, numSelectMax, true);
}
Aggregations