use of boofcv.core.image.border.ImageBorder_F32 in project BoofCV by lessthanoptimal.
the class ImplEdgeNonMaxSuppression method naive8.
/**
* Slow algorithm which processes the whole image.
*/
public static void naive8(GrayF32 _intensity, GrayS8 direction, GrayF32 output) {
final int w = _intensity.width;
final int h = _intensity.height;
ImageBorder_F32 intensity = (ImageBorder_F32) FactoryImageBorderAlgs.value(_intensity, 0);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int dir = direction.get(x, y);
int dx, dy;
if (dir == 0 || dir == 4) {
dx = 1;
dy = 0;
} else if (dir == 1 || dir == -3) {
dx = 1;
dy = 1;
} else if (dir == 2 || dir == -2) {
dx = 0;
dy = 1;
} else {
dx = 1;
dy = -1;
}
float left = intensity.get(x - dx, y - dy);
float middle = intensity.get(x, y);
float right = intensity.get(x + dx, y + dy);
// suppress the value if either of its neighboring values are more than or equal to it
if (left > middle || right > middle) {
output.set(x, y, 0);
} else {
output.set(x, y, middle);
}
}
}
}
use of boofcv.core.image.border.ImageBorder_F32 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 boofcv.core.image.border.ImageBorder_F32 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 boofcv.core.image.border.ImageBorder_F32 in project BoofCV by lessthanoptimal.
the class ImplEdgeNonMaxSuppression method naive4.
/**
* Slow algorithm which processes the whole image.
*/
public static void naive4(GrayF32 _intensity, GrayS8 direction, GrayF32 output) {
final int w = _intensity.width;
final int h = _intensity.height;
ImageBorder_F32 intensity = (ImageBorder_F32) FactoryImageBorderAlgs.value(_intensity, 0);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int dir = direction.get(x, y);
int dx, dy;
if (dir == 0) {
dx = 1;
dy = 0;
} else if (dir == 1) {
dx = 1;
dy = 1;
} else if (dir == 2) {
dx = 0;
dy = 1;
} else {
dx = 1;
dy = -1;
}
float left = intensity.get(x - dx, y - dy);
float middle = intensity.get(x, y);
float right = intensity.get(x + dx, y + dy);
// suppress the value if either of its neighboring values are more than or equal to it
if (left > middle || right > middle) {
output.set(x, y, 0);
} else {
output.set(x, y, middle);
}
}
}
}
use of boofcv.core.image.border.ImageBorder_F32 in project BoofCV by lessthanoptimal.
the class ImplEdgeNonMaxSuppression method border4.
/**
* Just processes the image border.
*/
public static void border4(GrayF32 _intensity, GrayS8 direction, GrayF32 output) {
int w = _intensity.width;
int h = _intensity.height - 1;
ImageBorder_F32 intensity = (ImageBorder_F32) FactoryImageBorderAlgs.value(_intensity, 0);
// top border
for (int x = 0; x < w; x++) {
int dir = direction.get(x, 0);
int dx, dy;
if (dir == 0) {
dx = 1;
dy = 0;
} else if (dir == 1) {
dx = 1;
dy = 1;
} else if (dir == 2) {
dx = 0;
dy = 1;
} else {
dx = 1;
dy = -1;
}
float left = intensity.get(x - dx, -dy);
float middle = intensity.get(x, 0);
float right = intensity.get(x + dx, dy);
if (left > middle || right > middle) {
output.set(x, 0, 0);
} else {
output.set(x, 0, middle);
}
}
// bottom border
for (int x = 0; x < w; x++) {
int dir = direction.get(x, h);
int dx, dy;
if (dir == 0) {
dx = 1;
dy = 0;
} else if (dir == 1) {
dx = 1;
dy = 1;
} else if (dir == 2) {
dx = 0;
dy = 1;
} else {
dx = 1;
dy = -1;
}
float left = intensity.get(x - dx, h - dy);
float middle = intensity.get(x, h);
float right = intensity.get(x + dx, h + dy);
if (left > middle || right > middle) {
output.set(x, h, 0);
} else {
output.set(x, h, middle);
}
}
// left border
for (int y = 1; y < h; y++) {
int dir = direction.get(0, y);
int dx, dy;
if (dir == 0) {
dx = 1;
dy = 0;
} else if (dir == 1) {
dx = 1;
dy = 1;
} else if (dir == 2) {
dx = 0;
dy = 1;
} else {
dx = 1;
dy = -1;
}
float left = intensity.get(-dx, y - dy);
float middle = intensity.get(0, y);
float right = intensity.get(dx, y + dy);
if (left > middle || right > middle) {
output.set(0, y, 0);
} else {
output.set(0, y, middle);
}
}
// right border
w = w - 1;
for (int y = 1; y < h; y++) {
int dir = direction.get(w, y);
int dx, dy;
if (dir == 0) {
dx = 1;
dy = 0;
} else if (dir == 1) {
dx = 1;
dy = 1;
} else if (dir == 2) {
dx = 0;
dy = 1;
} else {
dx = 1;
dy = -1;
}
float left = intensity.get(w - dx, y - dy);
float middle = intensity.get(w, y);
float right = intensity.get(w + dx, y + dy);
if (left > middle || right > middle) {
output.set(w, y, 0);
} else {
output.set(w, y, middle);
}
}
}
Aggregations