// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalan at live.com
//
// Copyright © Andrew Kirillov, 2007-2013
// andrew.kirillov@gmail.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
package Catalano.Imaging.Corners;
import Catalano.Core.IntPoint;
import Catalano.Imaging.FastBitmap;
import java.util.ArrayList;
import java.util.List;
/**
* Susan corners detector.
* The class implements Susan corners detector, which is described by S.M. Smith in: S.M. Smith, "SUSAN - a new approach to low level image processing", Internal Technical Report TR95SMS1, Defense Research Agency, Chobham Lane, Chertsey, Surrey, UK, 1995.
* @author Diego Catalano
*/
public class SusanCornersDetector implements ICornersDetector{
private int differenceThreshold = 25;
private int geometricalThreshold = 18;
private List corners = new ArrayList();
private int[] rowRadius = { 1, 2, 3, 3, 3, 2, 1 };
/**
* Initialize a new instance of the SusanCornersDetector class.
*/
public SusanCornersDetector() {
}
/**
* Initialize a new instance of the SusanCornersDetector class.
* @param differenceThreshold Brightness difference threshold.
* @param geometricalThreshold Geometrical threshold.
*/
public SusanCornersDetector(int differenceThreshold, int geometricalThreshold) {
this.differenceThreshold = differenceThreshold;
this.geometricalThreshold = geometricalThreshold;
}
/**
* Get Brightness difference threshold.
* @return Brightness difference threshold.
*/
public int getDifferenceThreshold() {
return differenceThreshold;
}
/**
* Set Brightness difference threshold.
* @param differenceThreshold Brightness difference threshold.
*/
public void setDifferenceThreshold(int differenceThreshold) {
this.differenceThreshold = differenceThreshold;
}
/**
* Get Geometrical threshold.
* @return Geometrical threshold.
*/
public int getGeometricalThreshold() {
return geometricalThreshold;
}
/**
* Set Geometrical threshold.
* @param geometricalThreshold Geometrical threshold.
*/
public void setGeometricalThreshold(int geometricalThreshold) {
this.geometricalThreshold = geometricalThreshold;
}
/**
* Process image looking for corners.
* @param fastBitmap FastBitmap for find corners.
* @return A list of points considered corners.
*/
@Override
public List ProcessImage(FastBitmap fastBitmap){
FastBitmap l = new FastBitmap(fastBitmap);
if (fastBitmap.isRGB()) l.toGrayscale();
int width = l.getWidth();
int height = l.getHeight();
int[][] susanMap = new int[height][width];
for (int x = 3; x < height - 3; x++) {
for (int y = 3; y < width - 3; y++) {
int nucleusValue = l.getGray(x, y);
int usan = 0;
int cx = 0, cy = 0;
for (int i = -3; i <= 3; i++) {
int r = rowRadius[i + 3];
for ( int j = -r; j <= r; j++ ){
int gray = l.getGray(x + i, y + j);
// differenceThreshold
if ( Math.abs( nucleusValue - gray ) <= differenceThreshold ){
usan++;
cx += x + j;
cy += y + i;
}
}
}
// check usan size
if ( usan < geometricalThreshold ){
cx /= usan;
cy /= usan;
if ( ( x != cx ) || ( y != cy ) ){
usan = ( geometricalThreshold - usan );
}
else{
usan = 0;
}
}
else{
usan = 0;
}
// usan = ( usan < geometricalThreshold ) ? ( geometricalThreshold - usan ) : 0;
susanMap[x][y] = usan;
}
}
// for each row
for ( int x = 2; x < height - 2; x++ ){
// for each pixel
for ( int y = 2; y < width - 2; y++ ){
int currentValue = susanMap[x][y];
// for each windows' row
for ( int i = -2; ( currentValue != 0 ) && ( i <= 2 ); i++ ){
// for each windows' pixel
for ( int j = -2; j <= 2; j++ ){
if ( susanMap[x+i][y+j] > currentValue ){
currentValue = 0;
break;
}
}
}
// check if this point is really interesting
if ( currentValue != 0 ){
corners.add( new IntPoint( x, y ) );
}
}
}
return corners;
}
}
Ads help maintain this website.