/*
* This file is part of the JFeatureLib project: https://github.com/locked-fg/JFeatureLib
* JFeatureLib is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* JFeatureLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JFeatureLib; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* You are kindly asked to refer to the papers of the according authors which
* should be mentioned in the Javadocs of the respective classes as well as the
* JFeatureLib project itself.
*
* Hints how to cite the projects can be found at
* https://github.com/locked-fg/JFeatureLib/wiki/Citation
*
* ##########################################################
* FAST Corner Detector
*
* FAST was first published By Edward Rosten in 2005, 2006:<br>
* - Fusing points and lines for high performance tracking (2005) and<br>
* - Machine learning for high-speed corner detection (2006).
*
* Please see http://www.edwardrosten.com/work/fast.html for links to the according papers, more information
* and other reference implementations. At this page you can also find BSD-licensed code.
*
* In case of using this code, the above copyright notive must retain the attribution to the author.
*/
package de.lmu.ifi.dbs.jfeaturelib.pointDetector.FAST;
import de.lmu.ifi.dbs.jfeaturelib.ImagePoint;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Robert Zelhofer
*/
public class FASTNonMaxSuppression {
private boolean compare(double x, double y) {
return x >= y;
}
public List<ImagePoint> nonmax_suppression(List<ImagePoint> corners, int[] scores, int num_corners) {
int num_nonmax = 0;
int last_row;
int[] row_start;
int i, j;
List<ImagePoint> ret_nonmax = new ArrayList<>();
int sz = num_corners;
/*Point above points (roughly) to the pixel above the one of interest, if there
is a feature there.*/
int point_above = 0;
int point_below = 0;
if (num_corners < 1) {
return ret_nonmax;
}
/* Find where each row begins
(the corners are output in raster scan order). A beginning of -1 signifies
that there are no corners on that row. */
last_row = (int)corners.get(num_corners - 1).y;
row_start = new int[last_row + 1];
for (i = 0; i < last_row + 1; i++) {
row_start[i] = -1;
}
{
int prev_row = -1;
for (i = 0; i < num_corners; i++) {
if ((int)corners.get(i).y != prev_row) {
row_start[(int)corners.get(i).y] = i;
prev_row = (int)corners.get(i).y;
}
}
}
for (i = 0; i < sz; i++) {
boolean isCorner = false;
int score = scores[i];
ImagePoint pos = corners.get(i);
/*Check left */
if (i > 0) {
if (corners.get(i - 1).x == pos.x - 1 && corners.get(i - 1).y == pos.y && compare(scores[i - 1], score)) {
continue;
}
}
/*Check right*/
if (i < (sz - 1)) {
if (corners.get(i + 1).x == pos.x + 1 && corners.get(i + 1).y == pos.y && compare(scores[i + 1], score)) {
continue;
}
}
/*Check above (if there is a valid row above)*/
if (pos.y != 0 && row_start[(int)pos.y - 1] != -1) {
/*Make sure that current point_above is one
row above.*/
if (corners.get(point_above).y < pos.y - 1) {
point_above = row_start[(int)pos.y - 1];
}
/*Make point_above point to the first of the pixels above the current point,
if it exists.*/
for (; corners.get(point_above).y < pos.y && corners.get(point_above).x < pos.x - 1; point_above++) {
}
for (j = point_above; corners.get(j).y < pos.y && corners.get(j).x <= pos.x + 1; j++) {
double x = corners.get(j).x;
if ((x == pos.x - 1 || x == pos.x || x == pos.x + 1) && compare(scores[j], score)) {
isCorner = false;
continue;
} else {
isCorner = true;
}
}
}
/*Check below (if there is anything below)*/
if (pos.y != last_row && row_start[(int)pos.y + 1] != -1 && point_below < sz) /*Nothing below*/ {
if (corners.get(point_below).y < pos.y + 1) {
point_below = row_start[(int)pos.y + 1];
}
/* Make point below point to one of the pixels belowthe current point, if it
exists.*/
for (; point_below < sz && corners.get(point_below).y == pos.y + 1 && corners.get(point_below).x < pos.x - 1; point_below++) {
}
for (j = point_below; j < sz && corners.get(j).y == pos.y + 1 && corners.get(j).x <= pos.x + 1; j++) {
double x = corners.get(j).x;
if ((x == pos.x - 1 || x == pos.x || x == pos.x + 1) && compare(scores[j], score)) {
isCorner = false;
continue;
} else {
isCorner = true;
}
}
}
ret_nonmax.add(corners.get(i));
}
return ret_nonmax;
}
}