2870 lines
128 KiB
C
2870 lines
128 KiB
C
/**********************************************************************\
|
|
|
|
SUSAN Version 2l by Stephen Smith
|
|
Oxford Centre for Functional Magnetic Resonance Imaging of the Brain,
|
|
Department of Clinical Neurology, Oxford University, Oxford, UK
|
|
(Previously in Computer Vision and Image Processing Group - now
|
|
Computer Vision and Electro Optics Group - DERA Chertsey, UK)
|
|
Email: steve@fmrib.ox.ac.uk
|
|
WWW: http://www.fmrib.ox.ac.uk/~steve
|
|
|
|
(C) Crown Copyright (1995-1999), Defence Evaluation and Research Agency,
|
|
Farnborough, Hampshire, GU14 6TD, UK
|
|
DERA WWW site:
|
|
http://www.dera.gov.uk/
|
|
DERA Computer Vision and Electro Optics Group WWW site:
|
|
http://www.dera.gov.uk/imageprocessing/dera/group_home.html
|
|
DERA Computer Vision and Electro Optics Group point of contact:
|
|
Dr. John Savage, jtsavage@dera.gov.uk, +44 1344 633203
|
|
|
|
A UK patent has been granted: "Method for digitally processing
|
|
images to determine the position of edges and/or corners therein for
|
|
guidance of unmanned vehicle", UK Patent 2272285. Proprietor:
|
|
Secretary of State for Defence, UK. 15 January 1997
|
|
|
|
This code is issued for research purposes only and remains the
|
|
property of the UK Secretary of State for Defence. This code must
|
|
not be passed on without this header information being kept
|
|
intact. This code must not be sold.
|
|
|
|
\**********************************************************************/
|
|
|
|
/**********************************************************************\
|
|
|
|
SUSAN Version 2l
|
|
SUSAN = Smallest Univalue Segment Assimilating Nucleus
|
|
|
|
Email: steve@fmrib.ox.ac.uk
|
|
WWW: http://www.fmrib.ox.ac.uk/~steve
|
|
|
|
Related paper:
|
|
@article{Smith97,
|
|
author = "Smith, S.M. and Brady, J.M.",
|
|
title = "{SUSAN} - A New Approach to Low Level Image Processing",
|
|
journal = "Int. Journal of Computer Vision",
|
|
pages = "45--78",
|
|
volume = "23",
|
|
number = "1",
|
|
month = "May",
|
|
year = 1997}
|
|
|
|
To be registered for automatic (bug) updates of SUSAN, send an email.
|
|
|
|
Compile with:
|
|
gcc -O4 -o susan susan2l.c -lm
|
|
|
|
See following section for different machine information. Please
|
|
report any bugs (and fixes). There are a few optional changes that
|
|
can be made in the "defines" section which follows shortly.
|
|
|
|
Usage: type "susan" to get usage. Only PGM format files can be input
|
|
and output. Utilities such as the netpbm package and XV can be used
|
|
to convert to and from other formats. Any size of image can be
|
|
processed.
|
|
|
|
This code is written using an emacs folding mode, making moving
|
|
around the different sections very easy. This is why there are
|
|
various marks within comments and why comments are indented.
|
|
|
|
|
|
SUSAN QUICK:
|
|
|
|
This version of the SUSAN corner finder does not do all the
|
|
false-corner suppression and thus is faster and produced some false
|
|
positives, particularly on strong edges. However, because there are
|
|
less stages involving thresholds etc., the corners that are
|
|
correctly reported are usually more stable than those reported with
|
|
the full algorithm. Thus I recommend at least TRYING this algorithm
|
|
for applications where stability is important, e.g., tracking.
|
|
|
|
THRESHOLDS:
|
|
|
|
There are two thresholds which can be set at run-time. These are the
|
|
brightness threshold (t) and the distance threshold (d).
|
|
|
|
SPATIAL CONTROL: d
|
|
|
|
In SUSAN smoothing d controls the size of the Gaussian mask; its
|
|
default is 4.0. Increasing d gives more smoothing. In edge finding,
|
|
a fixed flat mask is used, either 37 pixels arranged in a "circle"
|
|
(default), or a 3 by 3 mask which gives finer detail. In corner
|
|
finding, only the larger 37 pixel mask is used; d is not
|
|
variable. In smoothing, the flat 3 by 3 mask can be used instead of
|
|
a larger Gaussian mask; this gives low smoothing and fast operation.
|
|
|
|
BRIGHTNESS CONTROL: t
|
|
|
|
In all three algorithms, t can be varied (default=20); this is the
|
|
main threshold to be varied. It determines the maximum difference in
|
|
greylevels between two pixels which allows them to be considered
|
|
part of the same "region" in the image. Thus it can be reduced to
|
|
give more edges or corners, i.e. to be more sensitive, and vice
|
|
versa. In smoothing, reducing t gives less smoothing, and vice
|
|
versa. Set t=10 for the test image available from the SUSAN web
|
|
page.
|
|
|
|
ITERATIONS:
|
|
|
|
With SUSAN smoothing, more smoothing can also be obtained by
|
|
iterating the algorithm several times. This has a different effect
|
|
from varying d or t.
|
|
|
|
FIXED MASKS:
|
|
|
|
37 pixel mask: ooo 3 by 3 mask: ooo
|
|
ooooo ooo
|
|
ooooooo ooo
|
|
ooooooo
|
|
ooooooo
|
|
ooooo
|
|
ooo
|
|
|
|
CORNER ATTRIBUTES dx, dy and I
|
|
(Only read this if you are interested in the C implementation or in
|
|
using corner attributes, e.g., for corner matching)
|
|
|
|
Corners reported in the corner list have attributes associated with
|
|
them as well as positions. This is useful, for example, when
|
|
attempting to match corners from one image to another, as these
|
|
attributes can often be fairly unchanged between images. The
|
|
attributes are dx, dy and I. I is the value of image brightness at
|
|
the position of the corner. In the case of susan_corners_quick, dx
|
|
and dy are the first order derivatives (differentials) of the image
|
|
brightness in the x and y directions respectively, at the position
|
|
of the corner. In the case of normal susan corner finding, dx and dy
|
|
are scaled versions of the position of the centre of gravity of the
|
|
USAN with respect to the centre pixel (nucleus).
|
|
|
|
BRIGHTNESS FUNCTION LUT IMPLEMENTATION:
|
|
(Only read this if you are interested in the C implementation)
|
|
|
|
The SUSAN brightness function is implemented as a LUT
|
|
(Look-Up-Table) for speed. The resulting pointer-based code is a
|
|
little hard to follow, so here is a brief explanation. In
|
|
setup_brightness_lut() the LUT is setup. This mallocs enough space
|
|
for *bp and then repositions the pointer to the centre of the
|
|
malloced space. The SUSAN function e^-(x^6) or e^-(x^2) is
|
|
calculated and converted to a uchar in the range 0-100, for all
|
|
possible image brightness differences (including negative
|
|
ones). Thus bp[ 23 ] is the output for a brightness difference of 23
|
|
greylevels. In the SUSAN algorithms this LUT is used as follows:
|
|
|
|
p=in + (i-3)*x_size + j - 1;
|
|
p points to the first image pixel in the circular mask surrounding
|
|
point (x,y).
|
|
|
|
cp=bp + in[ i*x_size+j ];
|
|
cp points to a position in the LUT corresponding to the brightness
|
|
of the centre pixel (x,y).
|
|
|
|
now for every pixel within the mask surrounding (x,y),
|
|
n+=*(cp-*p++);
|
|
the brightness difference function is found by moving the cp pointer
|
|
down by an amount equal to the value of the pixel pointed to by p,
|
|
thus subtracting the two brightness values and performing the
|
|
exponential function. This value is added to n, the running USAN
|
|
area.
|
|
|
|
in SUSAN smoothing, the variable height mask is implemented by
|
|
multiplying the above by the moving mask pointer, reset for each new
|
|
centre pixel.
|
|
tmp = *dpt++ * *(cp-brightness);
|
|
|
|
\**********************************************************************/
|
|
|
|
/**********************************************************************\
|
|
|
|
Success has been reported with the following:
|
|
|
|
MACHINE OS COMPILER
|
|
|
|
Sun 4.1.4 bundled C, gcc
|
|
|
|
Next
|
|
|
|
SGI IRIX SGI cc
|
|
|
|
DEC Unix V3.2+
|
|
|
|
IBM RISC AIX gcc
|
|
|
|
PC Borland 5.0
|
|
|
|
PC Linux gcc-2.6.3
|
|
|
|
PC Win32 Visual C++ 4.0 (Console Application)
|
|
|
|
PC Win95 Visual C++ 5.0 (Console Application)
|
|
Thanks to Niu Yongsheng <niuysbit@163.net>:
|
|
Use the FOPENB option below
|
|
|
|
PC DOS djgpp gnu C
|
|
Thanks to Mark Pettovello
|
|
<mpettove@umdsun2.umd.umich.edu>: Use the FOPENB option below
|
|
|
|
HP HP-UX bundled cc
|
|
Thanks to Brian Dixon <briand@hpcvsgen.cv.hp.com>:
|
|
in ksh:
|
|
export CCOPTS="-Aa -D_HPUX_SOURCE | -lM"
|
|
cc -O3 -o susan susan2l.c
|
|
|
|
\**********************************************************************/
|
|
|
|
/**********************************************************************\
|
|
|
|
SUSAN Version 2l, 12/2/99
|
|
Changed GNUDOS option to FOPENB.
|
|
(Thanks to Niu Yongsheng <niuysbit@163.net>.)
|
|
Took out redundant "sq=sq/2;".
|
|
|
|
SUSAN Version 2k, 19/8/98:
|
|
In corner finding:
|
|
Changed if(yy<sq) {...} else if(xx<sq) {...} to
|
|
if(yy<xx) {...} else {...}
|
|
(Thanks to adq@cim.mcgill.edu - Alain Domercq.)
|
|
|
|
SUSAN Version 2j, 22/10/97:
|
|
Fixed (mask_size>x_size) etc. tests in smoothing.
|
|
Added a couple of free() calls for cgx and cgy.
|
|
(Thanks to geoffb@ucs.ed.ac.uk - Geoff Browitt.)
|
|
|
|
SUSAN Version 2i, 21/7/97:
|
|
Added information about corner attributes.
|
|
|
|
SUSAN Version 2h, 16/12/96:
|
|
Added principle (initial enhancement) option.
|
|
|
|
SUSAN Version 2g, 2/7/96:
|
|
Minor superficial changes to code.
|
|
|
|
SUSAN Version 2f, 16/1/96:
|
|
Added GNUDOS option (now called FOPENB; see options below).
|
|
|
|
SUSAN Version 2e, 9/1/96:
|
|
Added -b option.
|
|
Fixed 1 pixel horizontal offset error for drawing edges.
|
|
|
|
SUSAN Version 2d, 27/11/95:
|
|
Fixed loading of certain PGM files in get_image (again!)
|
|
|
|
SUSAN Version 2c, 22/11/95:
|
|
Fixed loading of certain PGM files in get_image.
|
|
(Thanks to qu@San-Jose.ate.slb.com - Gongyuan Qu.)
|
|
|
|
SUSAN Version 2b, 9/11/95:
|
|
removed "z==" error in edges routines.
|
|
|
|
SUSAN Version 2a, 6/11/95:
|
|
Removed a few unnecessary variable declarations.
|
|
Added different machine information.
|
|
Changed "header" in get_image to char.
|
|
|
|
SUSAN Version 2, 1/11/95: first combined version able to take any
|
|
image sizes.
|
|
|
|
SUSAN "Versions 1", circa 1992: the various SUSAN algorithms were
|
|
developed during my doctorate within different programs and for
|
|
fixed image sizes. The algorithms themselves are virtually unaltered
|
|
between "versions 1" and the combined program, version 2.
|
|
|
|
\**********************************************************************/
|
|
|
|
#include "wccfile.h"
|
|
#include "wcclibm.h"
|
|
#include "wccmalloc.h"
|
|
|
|
// Wasm loop bounds
|
|
|
|
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
|
|
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
|
|
|
|
#define EXP_A 184
|
|
#define EXP_C 16249
|
|
|
|
float
|
|
susan_expf(float y) {
|
|
union {
|
|
float d;
|
|
struct {
|
|
#ifdef LITTLE_ENDIAN
|
|
short j, i;
|
|
#else
|
|
short i, j;
|
|
#endif
|
|
} n;
|
|
} eco;
|
|
eco.n.i = EXP_A * (y) + (EXP_C);
|
|
eco.n.j = 0;
|
|
return eco.d;
|
|
}
|
|
|
|
float
|
|
susan_sqrtf(float val) {
|
|
float x = val / 10;
|
|
|
|
float dx;
|
|
|
|
float diff;
|
|
float min_tol = 0.00001f;
|
|
|
|
int i, flag;
|
|
|
|
flag = 0;
|
|
if (val == 0)
|
|
x = 0;
|
|
else {
|
|
__pragma_loopbound(19, 19);
|
|
for (i = 1; i < 20; i++) {
|
|
if (!flag) {
|
|
dx = (val - (x * x)) / (2.0f * x);
|
|
x = x + dx;
|
|
diff = val - (x * x);
|
|
if (fabs(diff) <= min_tol)
|
|
flag = 1;
|
|
}
|
|
}
|
|
}
|
|
return (x);
|
|
}
|
|
|
|
/* ********** Optional settings */
|
|
|
|
typedef int TOTAL_TYPE;
|
|
|
|
#define SEVEN_SUPP /* size for non-max corner suppression; SEVEN_SUPP or \
|
|
FIVE_SUPP */
|
|
#define MAX_CORNERS 15000 /* max corners per frame */
|
|
|
|
#define FTOI(a) ((a) < 0 ? ((int) (a - 0.5)) : ((int) (a + 0.5)))
|
|
#define abs(a) ((a) < 0 ? -a : a)
|
|
typedef unsigned char uchar;
|
|
typedef struct {
|
|
int x, y, info, dx, dy, I;
|
|
} corner_rep;
|
|
typedef corner_rep CORNER_LIST[MAX_CORNERS];
|
|
|
|
extern char susan_input[7292];
|
|
struct wccFILE susan_file;
|
|
float susan_dt;
|
|
int susan_bt;
|
|
int susan_principle_conf;
|
|
int susan_thin_post_proc;
|
|
int susan_three_by_three;
|
|
int susan_drawing_mode;
|
|
int susan_susan_quick;
|
|
int susan_max_no_corners;
|
|
int susan_max_no_edges;
|
|
|
|
int
|
|
susan_getint(struct wccFILE *fd) {
|
|
int c, i;
|
|
char dummy[10000];
|
|
|
|
c = susan_wccfgetc(fd);
|
|
__pragma_loopbound(0, 3);
|
|
while (1) { /* find next integer */
|
|
if (c == '#') /* if we're at a comment, read to end of line */
|
|
susan_wccfgets(dummy, 9000, fd);
|
|
if (c == EOF) {
|
|
/* "Image is not binary PGM." */
|
|
}
|
|
if (c >= '0' && c <= '9')
|
|
break; /* found what we were looking for */
|
|
c = susan_wccfgetc(fd);
|
|
}
|
|
|
|
/* we're at the start of a number, continue until we hit a non-number */
|
|
i = 0;
|
|
__pragma_loopbound(1, 2);
|
|
while (1) {
|
|
i = (i * 10) + (c - '0');
|
|
c = susan_wccfgetc(fd);
|
|
if (c == EOF)
|
|
return (i);
|
|
if (c < '0' || c > '9')
|
|
break;
|
|
}
|
|
|
|
return (i);
|
|
}
|
|
|
|
void
|
|
susan_get_image(struct wccFILE *fd, unsigned char **in, int *x_size,
|
|
int *y_size) {
|
|
char header[100];
|
|
|
|
susan_wccfseek(fd, 0, WCCSEEK_SET);
|
|
|
|
/* {{{ read header */
|
|
|
|
header[0] = susan_wccfgetc(fd);
|
|
header[1] = susan_wccfgetc(fd);
|
|
if (!(header[0] == 'P' && header[1] == '5')) {
|
|
/* "Image does not have binary PGM header." */
|
|
}
|
|
|
|
*x_size = susan_getint(fd);
|
|
*y_size = susan_getint(fd);
|
|
// dummy read
|
|
susan_getint(fd);
|
|
|
|
/* }}} */
|
|
|
|
*in = (uchar *) susan_wccmalloc(*x_size * *y_size);
|
|
|
|
if (susan_wccfread(*in, 1, *x_size * *y_size, fd) == 0) {
|
|
/* "Image is wrong size.\n" */
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_put_image(int x_size, int y_size) {
|
|
int i;
|
|
__pragma_loopbound(7220, 7220);
|
|
for (i = 0; i < x_size * y_size; i++)
|
|
;
|
|
}
|
|
|
|
void
|
|
susan_int_to_uchar(char *r, uchar *in, int size) {
|
|
int i, max_r = r[0], min_r = r[0];
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 0; i < size; i++) {
|
|
if (r[i] > max_r)
|
|
max_r = r[i];
|
|
if (r[i] < min_r)
|
|
min_r = r[i];
|
|
}
|
|
|
|
if (max_r == min_r) {
|
|
/* Should not occur in TACLeBench. */
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 0; i < size; i++)
|
|
in[i] = (uchar) (0);
|
|
|
|
return;
|
|
}
|
|
max_r -= min_r;
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 0; i < size; i++)
|
|
in[i] = (uchar) ((int) ((int) (r[i] - min_r) * 255) / max_r);
|
|
}
|
|
|
|
void
|
|
susan_setup_brightness_lut(uchar **bp, int thresh, int form) {
|
|
int k;
|
|
float temp;
|
|
|
|
*bp = (unsigned char *) susan_wccmalloc(516);
|
|
*bp = *bp + 258;
|
|
|
|
__pragma_loopbound(513, 513);
|
|
for (k = -256; k < 257; k++) {
|
|
temp = ((float) k) / ((float) thresh);
|
|
temp = temp * temp;
|
|
if (form == 6)
|
|
temp = temp * temp * temp;
|
|
temp = 100.0 * susan_expf(-temp);
|
|
*(*bp + k) = (uchar) temp;
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_principle(uchar *in, char *r, uchar *bp, int max_no, int x_size,
|
|
int y_size) {
|
|
int i, j, n;
|
|
uchar *p, *cp;
|
|
|
|
susan_wccmemset(r, 0, x_size * y_size * sizeof(int));
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 3; i < y_size - 3; i++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (j = 3; j < x_size - 3; j++) {
|
|
n = 100;
|
|
p = in + (i - 3) * x_size + j - 1;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 3;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += 2;
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 3;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
|
|
if (n <= max_no)
|
|
r[i * x_size + j] = max_no - n;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_principle_small(uchar *in, char *r, uchar *bp, int max_no, int x_size,
|
|
int y_size) {
|
|
int i, j, n;
|
|
uchar *p, *cp;
|
|
|
|
susan_wccmemset(r, 0, x_size * y_size * sizeof(int));
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 1; i < y_size - 1; i++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (j = 1; j < x_size - 1; j++) {
|
|
n = 100;
|
|
p = in + (i - 1) * x_size + j - 1;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 2;
|
|
|
|
n += *(cp - *p);
|
|
p += 2;
|
|
n += *(cp - *p);
|
|
p += x_size - 2;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
|
|
if (n <= max_no)
|
|
r[i * x_size + j] = max_no - n;
|
|
}
|
|
}
|
|
}
|
|
|
|
uchar
|
|
susan_median(uchar *in, int i, int j, int x_size) {
|
|
int p[8], k, l, tmp;
|
|
|
|
p[0] = in[(i - 1) * x_size + j - 1];
|
|
p[1] = in[(i - 1) * x_size + j];
|
|
p[2] = in[(i - 1) * x_size + j + 1];
|
|
p[3] = in[(i) *x_size + j - 1];
|
|
p[4] = in[(i) *x_size + j + 1];
|
|
p[5] = in[(i + 1) * x_size + j - 1];
|
|
p[6] = in[(i + 1) * x_size + j];
|
|
p[7] = in[(i + 1) * x_size + j + 1];
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (k = 0; k < 7; k++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (l = 0; l < (7 - k); l++) {
|
|
if (p[l] > p[l + 1]) {
|
|
tmp = p[l];
|
|
p[l] = p[l + 1];
|
|
p[l + 1] = tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ((p[3] + p[4]) / 2);
|
|
}
|
|
|
|
/* this enlarges "in" so that borders can be dealt with easily */
|
|
void
|
|
susan_enlarge(uchar **in, uchar *tmp_image, int *x_size, int *y_size,
|
|
int border) {
|
|
int i, j;
|
|
|
|
__pragma_loopbound(95, 95);
|
|
for (i = 0; i < *y_size; i++) { /* copy *in into tmp_image */
|
|
susan_wccmemcpy(tmp_image + (i + border) * (*x_size + 2 * border) +
|
|
border,
|
|
*in + i * *x_size, *x_size);
|
|
}
|
|
|
|
_Pragma(
|
|
"loopbound min 7 max 7") for (i = 0; i < border;
|
|
i++) { /* copy top and bottom rows; invert
|
|
as many as necessary */
|
|
susan_wccmemcpy(tmp_image + (border - 1 - i) * (*x_size + 2 * border) +
|
|
border,
|
|
*in + i * *x_size, *x_size);
|
|
susan_wccmemcpy(tmp_image +
|
|
(*y_size + border + i) * (*x_size + 2 * border) +
|
|
border,
|
|
*in + (*y_size - i - 1) * *x_size, *x_size);
|
|
}
|
|
|
|
_Pragma(
|
|
"loopbound min 7 max 7") for (i = 0; i < border;
|
|
i++) { /* copy left and right columns */
|
|
__pragma_loopbound(109, 109);
|
|
for (j = 0; j < *y_size + 2 * border; j++) {
|
|
tmp_image[j * (*x_size + 2 * border) + border - 1 - i] =
|
|
tmp_image[j * (*x_size + 2 * border) + border + i];
|
|
tmp_image[j * (*x_size + 2 * border) + *x_size + border + i] =
|
|
tmp_image[j * (*x_size + 2 * border) + *x_size + border - 1 -
|
|
i];
|
|
}
|
|
}
|
|
|
|
*x_size += 2 * border; /* alter image size */
|
|
*y_size += 2 * border;
|
|
*in = tmp_image; /* repoint in */
|
|
}
|
|
|
|
void
|
|
susan_smoothing(int three_by_three, uchar *in, float dt, int x_size, int y_size,
|
|
uchar *bp) {
|
|
float temp;
|
|
int n_max, increment, mask_size, i, j, x, y, area, brightness, tmp, centre;
|
|
uchar *ip, *dp, *dpt, *cp, *out = in, *tmp_image;
|
|
TOTAL_TYPE total;
|
|
|
|
/* {{{ setup larger image and border sizes */
|
|
|
|
if (three_by_three == 0)
|
|
mask_size = ((int) (1.5 * dt)) + 1;
|
|
else
|
|
mask_size = 1;
|
|
|
|
if (dt > 15) {
|
|
/* "Distance_thresh too big for integer arithmetic." */
|
|
// Either reduce it to <=15 or recompile with variable "total"
|
|
// as a float: see top "defines" section.
|
|
}
|
|
|
|
if ((2 * mask_size + 1 > x_size) || (2 * mask_size + 1 > y_size)) {
|
|
/* "Mask size too big for image." */
|
|
}
|
|
|
|
tmp_image = (uchar *) susan_wccmalloc((x_size + mask_size * 2) *
|
|
(y_size + mask_size * 2));
|
|
susan_enlarge(&in, tmp_image, &x_size, &y_size, mask_size);
|
|
if (three_by_three == 0) {
|
|
/* large Gaussian masks */
|
|
/* {{{ setup distance lut */
|
|
|
|
n_max = (mask_size * 2) + 1;
|
|
|
|
increment = x_size - n_max;
|
|
|
|
dp = (unsigned char *) susan_wccmalloc(n_max * n_max);
|
|
dpt = dp;
|
|
temp = -(dt * dt);
|
|
|
|
__pragma_loopbound(15, 15);
|
|
for (i = -mask_size; i <= mask_size; i++) {
|
|
__pragma_loopbound(15, 15);
|
|
for (j = -mask_size; j <= mask_size; j++) {
|
|
x = (int) (100.0 *
|
|
susan_expf(((float) ((i * i) + (j * j))) / temp));
|
|
*dpt++ = (unsigned char) x;
|
|
}
|
|
}
|
|
|
|
/* {{{ main section */
|
|
__pragma_loopbound(95, 95);
|
|
for (i = mask_size; i < y_size - mask_size; i++) {
|
|
__pragma_loopbound(76, 76);
|
|
for (j = mask_size; j < x_size - mask_size; j++) {
|
|
area = 0;
|
|
total = 0;
|
|
dpt = dp;
|
|
ip = in + ((i - mask_size) * x_size) + j - mask_size;
|
|
centre = in[i * x_size + j];
|
|
cp = bp + centre;
|
|
__pragma_loopbound(15, 15);
|
|
for (y = -mask_size; y <= mask_size; y++) {
|
|
__pragma_loopbound(15, 15);
|
|
for (x = -mask_size; x <= mask_size; x++) {
|
|
brightness = *ip++;
|
|
tmp = *dpt++ * *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
}
|
|
ip += increment;
|
|
}
|
|
tmp = area - 10000;
|
|
if (tmp == 0)
|
|
*out++ = susan_median(in, i, j, x_size);
|
|
else
|
|
*out++ = ((total - (centre * 10000)) / tmp);
|
|
}
|
|
}
|
|
} else {
|
|
/* 3x3 constant mask */
|
|
|
|
/* {{{ main section */
|
|
__pragma_loopbound(15, 15); // neue Änderung min max 107
|
|
for (i = 1; i < y_size - 1; i++) {
|
|
__pragma_loopbound(15, 15); // neue Änderung min max 88
|
|
for (j = 1; j < x_size - 1; j++) {
|
|
area = 0;
|
|
total = 0;
|
|
ip = in + ((i - 1) * x_size) + j - 1;
|
|
centre = in[i * x_size + j];
|
|
cp = bp + centre;
|
|
|
|
brightness = *ip++;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
brightness = *ip++;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
brightness = *ip;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
ip += x_size - 2;
|
|
brightness = *ip++;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
brightness = *ip++;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
brightness = *ip;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
ip += x_size - 2;
|
|
brightness = *ip++;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
brightness = *ip++;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
brightness = *ip;
|
|
tmp = *(cp - brightness);
|
|
area += tmp;
|
|
total += tmp * brightness;
|
|
|
|
tmp = area - 100;
|
|
if (tmp == 0)
|
|
*out++ = susan_median(in, i, j, x_size);
|
|
else
|
|
*out++ = (total - (centre * 100)) / tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_edge_draw(uchar *in, uchar *mid, int x_size, int y_size,
|
|
int drawing_mode) {
|
|
int i;
|
|
uchar *inp, *midp;
|
|
|
|
if (drawing_mode == 0) {
|
|
/* mark 3x3 white block around each edge point */
|
|
midp = mid;
|
|
__pragma_loopbound(7220, 7220);
|
|
for (i = 0; i < x_size * y_size; i++) {
|
|
if (*midp < 8) {
|
|
inp = in + (midp - mid) - x_size - 1;
|
|
*inp++ = 255;
|
|
*inp++ = 255;
|
|
*inp = 255;
|
|
inp += x_size - 2;
|
|
*inp++ = 255;
|
|
inp++;
|
|
*inp = 255;
|
|
inp += x_size - 2;
|
|
*inp++ = 255;
|
|
*inp++ = 255;
|
|
*inp = 255;
|
|
}
|
|
midp++;
|
|
}
|
|
}
|
|
|
|
/* now mark 1 black pixel at each edge point */
|
|
midp = mid;
|
|
__pragma_loopbound(7220, 7220);
|
|
for (i = 0; i < x_size * y_size; i++) {
|
|
if (*midp < 8)
|
|
*(in + (midp - mid)) = 0;
|
|
midp++;
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_thin(char *r, uchar *mid, int x_size, int y_size) {
|
|
int l[9], centre, b01, b12, b21, b10, p1, p2, p3, p4, b00, b02, b20, b22, m,
|
|
n, a, b, x, y, i, j;
|
|
uchar *mp;
|
|
|
|
__pragma_loopbound(87, 87);
|
|
for (i = 4; i < y_size - 4; i++) {
|
|
__pragma_loopbound(68, 68);
|
|
for (j = 4; j < x_size - 4; j++) {
|
|
if (mid[i * x_size + j] < 8) {
|
|
centre = r[i * x_size + j];
|
|
/* {{{ count number of neighbours */
|
|
|
|
mp = mid + (i - 1) * x_size + j - 1;
|
|
|
|
n = (*mp < 8) + (*(mp + 1) < 8) + (*(mp + 2) < 8) +
|
|
(*(mp + x_size) < 8) + (*(mp + x_size + 2) < 8) +
|
|
(*(mp + x_size + x_size) < 8) +
|
|
(*(mp + x_size + x_size + 1) < 8) +
|
|
(*(mp + x_size + x_size + 2) < 8);
|
|
|
|
/* {{{ n==0 no neighbours - remove point */
|
|
|
|
if (n == 0)
|
|
mid[i * x_size + j] = 100;
|
|
|
|
/* {{{ n==1 - extend line if I can */
|
|
|
|
/* extension is only allowed a few times - the value of mid is
|
|
* used to control this */
|
|
|
|
if ((n == 1) && (mid[i * x_size + j] < 6)) {
|
|
/* find maximum neighbour weighted in direction opposite the
|
|
neighbour already present. e.g.
|
|
have: O O O weight r by 0 2 3
|
|
X X O 0 0 4
|
|
O O O 0 2 3 */
|
|
|
|
l[0] = r[(i - 1) * x_size + j - 1];
|
|
l[1] = r[(i - 1) * x_size + j];
|
|
l[2] = r[(i - 1) * x_size + j + 1];
|
|
l[3] = r[(i) *x_size + j - 1];
|
|
l[4] = 0;
|
|
l[5] = r[(i) *x_size + j + 1];
|
|
l[6] = r[(i + 1) * x_size + j - 1];
|
|
l[7] = r[(i + 1) * x_size + j];
|
|
l[8] = r[(i + 1) * x_size + j + 1];
|
|
|
|
if (mid[(i - 1) * x_size + j - 1] < 8) {
|
|
l[0] = 0;
|
|
l[1] = 0;
|
|
l[3] = 0;
|
|
l[2] *= 2;
|
|
l[6] *= 2;
|
|
l[5] *= 3;
|
|
l[7] *= 3;
|
|
l[8] *= 4;
|
|
} else {
|
|
if (mid[(i - 1) * x_size + j] < 8) {
|
|
l[1] = 0;
|
|
l[0] = 0;
|
|
l[2] = 0;
|
|
l[3] *= 2;
|
|
l[5] *= 2;
|
|
l[6] *= 3;
|
|
l[8] *= 3;
|
|
l[7] *= 4;
|
|
} else {
|
|
if (mid[(i - 1) * x_size + j + 1] < 8) {
|
|
l[2] = 0;
|
|
l[1] = 0;
|
|
l[5] = 0;
|
|
l[0] *= 2;
|
|
l[8] *= 2;
|
|
l[3] *= 3;
|
|
l[7] *= 3;
|
|
l[6] *= 4;
|
|
} else {
|
|
if (mid[(i) *x_size + j - 1] < 8) {
|
|
l[3] = 0;
|
|
l[0] = 0;
|
|
l[6] = 0;
|
|
l[1] *= 2;
|
|
l[7] *= 2;
|
|
l[2] *= 3;
|
|
l[8] *= 3;
|
|
l[5] *= 4;
|
|
} else {
|
|
if (mid[(i) *x_size + j + 1] < 8) {
|
|
l[5] = 0;
|
|
l[2] = 0;
|
|
l[8] = 0;
|
|
l[1] *= 2;
|
|
l[7] *= 2;
|
|
l[0] *= 3;
|
|
l[6] *= 3;
|
|
l[3] *= 4;
|
|
} else {
|
|
if (mid[(i + 1) * x_size + j - 1] < 8) {
|
|
l[6] = 0;
|
|
l[3] = 0;
|
|
l[7] = 0;
|
|
l[0] *= 2;
|
|
l[8] *= 2;
|
|
l[1] *= 3;
|
|
l[5] *= 3;
|
|
l[2] *= 4;
|
|
} else {
|
|
if (mid[(i + 1) * x_size + j] < 8) {
|
|
l[7] = 0;
|
|
l[6] = 0;
|
|
l[8] = 0;
|
|
l[3] *= 2;
|
|
l[5] *= 2;
|
|
l[0] *= 3;
|
|
l[2] *= 3;
|
|
l[1] *= 4;
|
|
} else {
|
|
if (mid[(i + 1) * x_size + j +
|
|
1] < 8) {
|
|
l[8] = 0;
|
|
l[5] = 0;
|
|
l[7] = 0;
|
|
l[6] *= 2;
|
|
l[2] *= 2;
|
|
l[1] *= 3;
|
|
l[3] *= 3;
|
|
l[0] *= 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m = 0; /* find the highest point */
|
|
__pragma_loopbound(3, 3);
|
|
for (y = 0; y < 3; y++)
|
|
_Pragma(
|
|
"loopbound min 3 max 3") for (x = 0; x < 3;
|
|
x++) if (l[y + y + y +
|
|
x] > m) {
|
|
m = l[y + y + y + x];
|
|
a = y;
|
|
b = x;
|
|
}
|
|
|
|
if (m > 0) {
|
|
if (mid[i * x_size + j] < 4)
|
|
mid[(i + a - 1) * x_size + j + b - 1] = 4;
|
|
else
|
|
mid[(i + a - 1) * x_size + j + b - 1] =
|
|
mid[i * x_size + j] + 1;
|
|
if ((a + a + b) < 3) { /* need to jump back in image */
|
|
i += a - 1;
|
|
j += b - 2;
|
|
if (i < 4)
|
|
i = 4;
|
|
if (j < 4)
|
|
j = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* {{{ n==2 */
|
|
|
|
if (n == 2) {
|
|
/* put in a bit here to straighten edges */
|
|
b00 =
|
|
mid[(i - 1) * x_size + j - 1] < 8; /* corners of 3x3 */
|
|
b02 = mid[(i - 1) * x_size + j + 1] < 8;
|
|
b20 = mid[(i + 1) * x_size + j - 1] < 8;
|
|
b22 = mid[(i + 1) * x_size + j + 1] < 8;
|
|
if (((b00 + b02 + b20 + b22) == 2) &&
|
|
((b00 | b22) & (b02 | b20))) {
|
|
/* case: move a point back into line.
|
|
e.g. X O X CAN become X X X
|
|
O X O O O O
|
|
O O O O O O */
|
|
if (b00) {
|
|
if (b02) {
|
|
x = 0;
|
|
y = -1;
|
|
} else {
|
|
x = -1;
|
|
y = 0;
|
|
}
|
|
} else {
|
|
if (b02) {
|
|
x = 1;
|
|
y = 0;
|
|
} else {
|
|
x = 0;
|
|
y = 1;
|
|
}
|
|
}
|
|
if (((float) r[(i + y) * x_size + j + x] /
|
|
(float) centre) > 0.7) {
|
|
if (((x == 0) &&
|
|
(mid[(i + (2 * y)) * x_size + j] > 7) &&
|
|
(mid[(i + (2 * y)) * x_size + j - 1] > 7) &&
|
|
(mid[(i + (2 * y)) * x_size + j + 1] > 7)) ||
|
|
((y == 0) &&
|
|
(mid[(i) *x_size + j + (2 * x)] > 7) &&
|
|
(mid[(i + 1) * x_size + j + (2 * x)] > 7) &&
|
|
(mid[(i - 1) * x_size + j + (2 * x)] > 7))) {
|
|
mid[(i) *x_size + j] = 100;
|
|
mid[(i + y) * x_size + j + x] =
|
|
3; /* no jumping needed */
|
|
}
|
|
}
|
|
} else {
|
|
b01 = mid[(i - 1) * x_size + j] < 8;
|
|
b12 = mid[(i) *x_size + j + 1] < 8;
|
|
b21 = mid[(i + 1) * x_size + j] < 8;
|
|
b10 = mid[(i) *x_size + j - 1] < 8;
|
|
/* {{{ right angle ends - not currently used */
|
|
|
|
#ifdef IGNORETHIS
|
|
if ((b00 & b01) | (b00 & b10) | (b02 & b01) |
|
|
(b02 & b12) | (b20 & b10) | (b20 & b21) |
|
|
(b22 & b21) | (b22 & b12)) {
|
|
/* case; right angle ends. clean up.
|
|
e.g.; X X O CAN become X X O
|
|
O X O O O O
|
|
O O O O O O */
|
|
if (((b01) & (mid[(i - 2) * x_size + j - 1] > 7) &
|
|
(mid[(i - 2) * x_size + j] > 7) &
|
|
(mid[(i - 2) * x_size + j + 1] > 7) &
|
|
((b00 & ((2 * r[(i - 1) * x_size + j + 1]) >
|
|
centre)) |
|
|
(b02 & ((2 * r[(i - 1) * x_size + j - 1]) >
|
|
centre)))) |
|
|
((b10) & (mid[(i - 1) * x_size + j - 2] > 7) &
|
|
(mid[(i) *x_size + j - 2] > 7) &
|
|
(mid[(i + 1) * x_size + j - 2] > 7) &
|
|
((b00 & ((2 * r[(i + 1) * x_size + j - 1]) >
|
|
centre)) |
|
|
(b20 & ((2 * r[(i - 1) * x_size + j - 1]) >
|
|
centre)))) |
|
|
((b12) & (mid[(i - 1) * x_size + j + 2] > 7) &
|
|
(mid[(i) *x_size + j + 2] > 7) &
|
|
(mid[(i + 1) * x_size + j + 2] > 7) &
|
|
((b02 & ((2 * r[(i + 1) * x_size + j + 1]) >
|
|
centre)) |
|
|
(b22 & ((2 * r[(i - 1) * x_size + j + 1]) >
|
|
centre)))) |
|
|
((b21) & (mid[(i + 2) * x_size + j - 1] > 7) &
|
|
(mid[(i + 2) * x_size + j] > 7) &
|
|
(mid[(i + 2) * x_size + j + 1] > 7) &
|
|
((b20 & ((2 * r[(i + 1) * x_size + j + 1]) >
|
|
centre)) |
|
|
(b22 & ((2 * r[(i + 1) * x_size + j - 1]) >
|
|
centre))))) {
|
|
mid[(i) *x_size + j] = 100;
|
|
if (b10 & b20)
|
|
j -= 2;
|
|
if (b00 | b01 | b02) {
|
|
i--;
|
|
j -= 2;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (((b01 + b12 + b21 + b10) == 2) &&
|
|
((b10 | b12) & (b01 | b21)) &&
|
|
((b01 & ((mid[(i - 2) * x_size + j - 1] < 8) |
|
|
(mid[(i - 2) * x_size + j + 1] < 8))) |
|
|
(b10 & ((mid[(i - 1) * x_size + j - 2] < 8) |
|
|
(mid[(i + 1) * x_size + j - 2] < 8))) |
|
|
(b12 & ((mid[(i - 1) * x_size + j + 2] < 8) |
|
|
(mid[(i + 1) * x_size + j + 2] < 8))) |
|
|
(b21 & ((mid[(i + 2) * x_size + j - 1] < 8) |
|
|
(mid[(i + 2) * x_size + j + 1] < 8))))) {
|
|
/* case; clears odd right angles.
|
|
e.g.; O O O becomes O O O
|
|
X X O X O O
|
|
O X O O X O */
|
|
mid[(i) *x_size + j] = 100;
|
|
i--; /* jump back */
|
|
j -= 2;
|
|
if (i < 4)
|
|
i = 4;
|
|
if (j < 4)
|
|
j = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* {{{ n>2 the thinning is done here without breaking
|
|
* connectivity */
|
|
|
|
if (n > 2) {
|
|
b01 = mid[(i - 1) * x_size + j] < 8;
|
|
b12 = mid[(i) *x_size + j + 1] < 8;
|
|
b21 = mid[(i + 1) * x_size + j] < 8;
|
|
b10 = mid[(i) *x_size + j - 1] < 8;
|
|
if ((b01 + b12 + b21 + b10) > 1) {
|
|
b00 = mid[(i - 1) * x_size + j - 1] < 8;
|
|
b02 = mid[(i - 1) * x_size + j + 1] < 8;
|
|
b20 = mid[(i + 1) * x_size + j - 1] < 8;
|
|
b22 = mid[(i + 1) * x_size + j + 1] < 8;
|
|
p1 = b00 | b01;
|
|
p2 = b02 | b12;
|
|
p3 = b22 | b21;
|
|
p4 = b20 | b10;
|
|
|
|
if (((p1 + p2 + p3 + p4) - ((b01 & p2) + (b12 & p3) +
|
|
(b21 & p4) + (b10 & p1))) <
|
|
2) {
|
|
mid[(i) *x_size + j] = 100;
|
|
i--;
|
|
j -= 2;
|
|
if (i < 4)
|
|
i = 4;
|
|
if (j < 4)
|
|
j = 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_edges(uchar *in, char *r, uchar *mid, uchar *bp, int max_no, int x_size,
|
|
int y_size) {
|
|
float z;
|
|
int do_symmetry, i, j, m, n, a, b, x, y, w;
|
|
uchar c, *p, *cp;
|
|
|
|
susan_wccmemset(r, 0, x_size * y_size);
|
|
|
|
__pragma_loopbound(89, 89);
|
|
for (i = 3; i < y_size - 3; i++) {
|
|
__pragma_loopbound(70, 70);
|
|
for (j = 3; j < x_size - 3; j++) {
|
|
n = 100;
|
|
p = in + (i - 3) * x_size + j - 1;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 3;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += 2;
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 3;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
|
|
if (n <= max_no)
|
|
r[i * x_size + j] = max_no - n;
|
|
}
|
|
}
|
|
|
|
__pragma_loopbound(87, 87);
|
|
for (i = 4; i < y_size - 4; i++) {
|
|
__pragma_loopbound(68, 68);
|
|
for (j = 4; j < x_size - 4; j++) {
|
|
if (r[i * x_size + j] > 0) {
|
|
m = r[i * x_size + j];
|
|
n = max_no - m;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
if (n > 600) {
|
|
p = in + (i - 3) * x_size + j - 1;
|
|
x = 0;
|
|
y = 0;
|
|
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y -= 3 * c;
|
|
c = *(cp - *p++);
|
|
y -= 3 * c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y -= 3 * c;
|
|
p += x_size - 3;
|
|
|
|
c = *(cp - *p++);
|
|
x -= 2 * c;
|
|
y -= 2 * c;
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y -= 2 * c;
|
|
c = *(cp - *p++);
|
|
y -= 2 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y -= 2 * c;
|
|
c = *(cp - *p);
|
|
x += 2 * c;
|
|
y -= 2 * c;
|
|
p += x_size - 5;
|
|
|
|
c = *(cp - *p++);
|
|
x -= 3 * c;
|
|
y -= c;
|
|
c = *(cp - *p++);
|
|
x -= 2 * c;
|
|
y -= c;
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y -= c;
|
|
c = *(cp - *p++);
|
|
y -= c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y -= c;
|
|
c = *(cp - *p++);
|
|
x += 2 * c;
|
|
y -= c;
|
|
c = *(cp - *p);
|
|
x += 3 * c;
|
|
y -= c;
|
|
p += x_size - 6;
|
|
|
|
c = *(cp - *p++);
|
|
x -= 3 * c;
|
|
c = *(cp - *p++);
|
|
x -= 2 * c;
|
|
c = *(cp - *p);
|
|
x -= c;
|
|
p += 2;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
c = *(cp - *p++);
|
|
x += 2 * c;
|
|
c = *(cp - *p);
|
|
x += 3 * c;
|
|
p += x_size - 6;
|
|
|
|
c = *(cp - *p++);
|
|
x -= 3 * c;
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
x -= 2 * c;
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
x += 2 * c;
|
|
y += c;
|
|
c = *(cp - *p);
|
|
x += 3 * c;
|
|
y += c;
|
|
p += x_size - 5;
|
|
|
|
c = *(cp - *p++);
|
|
x -= 2 * c;
|
|
y += 2 * c;
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y += 2 * c;
|
|
c = *(cp - *p++);
|
|
y += 2 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 2 * c;
|
|
c = *(cp - *p);
|
|
x += 2 * c;
|
|
y += 2 * c;
|
|
p += x_size - 3;
|
|
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y += 3 * c;
|
|
c = *(cp - *p++);
|
|
y += 3 * c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y += 3 * c;
|
|
|
|
z = susan_sqrtf((float) ((x * x) + (y * y)));
|
|
if (z > (0.9 * (float) n)) { /* 0.5 */
|
|
do_symmetry = 0;
|
|
if (x == 0)
|
|
z = 1000000.0;
|
|
else
|
|
z = ((float) y) / ((float) x);
|
|
if (z < 0) {
|
|
z = -z;
|
|
w = -1;
|
|
} else
|
|
w = 1;
|
|
if (z < 0.5) {
|
|
/* vert_edge */ a = 0;
|
|
b = 1;
|
|
} else {
|
|
if (z > 2.0) {
|
|
/* hor_edge */ a = 1;
|
|
b = 0;
|
|
} else {
|
|
/* diag_edge */ if (w > 0) {
|
|
a = 1;
|
|
b = 1;
|
|
} else {
|
|
a = -1;
|
|
b = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((m > r[(i + a) * x_size + j + b]) &&
|
|
(m >= r[(i - a) * x_size + j - b]) &&
|
|
(m > r[(i + (2 * a)) * x_size + j + (2 * b)]) &&
|
|
(m >= r[(i - (2 * a)) * x_size + j - (2 * b)]))
|
|
mid[i * x_size + j] = 1;
|
|
} else
|
|
do_symmetry = 1;
|
|
} else
|
|
do_symmetry = 1;
|
|
|
|
if (do_symmetry == 1) {
|
|
p = in + (i - 3) * x_size + j - 1;
|
|
x = 0;
|
|
y = 0;
|
|
w = 0;
|
|
|
|
/* | \
|
|
y -x- w
|
|
| \ */
|
|
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 9 * c;
|
|
w += 3 * c;
|
|
c = *(cp - *p++);
|
|
y += 9 * c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y += 9 * c;
|
|
w -= 3 * c;
|
|
p += x_size - 3;
|
|
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
y += 4 * c;
|
|
w += 4 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 4 * c;
|
|
w += 2 * c;
|
|
c = *(cp - *p++);
|
|
y += 4 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 4 * c;
|
|
w -= 2 * c;
|
|
c = *(cp - *p);
|
|
x += 4 * c;
|
|
y += 4 * c;
|
|
w -= 4 * c;
|
|
p += x_size - 5;
|
|
|
|
c = *(cp - *p++);
|
|
x += 9 * c;
|
|
y += c;
|
|
w += 3 * c;
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
y += c;
|
|
w += 2 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
w += c;
|
|
c = *(cp - *p++);
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
w -= c;
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
y += c;
|
|
w -= 2 * c;
|
|
c = *(cp - *p);
|
|
x += 9 * c;
|
|
y += c;
|
|
w -= 3 * c;
|
|
p += x_size - 6;
|
|
|
|
c = *(cp - *p++);
|
|
x += 9 * c;
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
p += 2;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
c = *(cp - *p);
|
|
x += 9 * c;
|
|
p += x_size - 6;
|
|
|
|
c = *(cp - *p++);
|
|
x += 9 * c;
|
|
y += c;
|
|
w -= 3 * c;
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
y += c;
|
|
w -= 2 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
w -= c;
|
|
c = *(cp - *p++);
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
w += c;
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
y += c;
|
|
w += 2 * c;
|
|
c = *(cp - *p);
|
|
x += 9 * c;
|
|
y += c;
|
|
w += 3 * c;
|
|
p += x_size - 5;
|
|
|
|
c = *(cp - *p++);
|
|
x += 4 * c;
|
|
y += 4 * c;
|
|
w -= 4 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 4 * c;
|
|
w -= 2 * c;
|
|
c = *(cp - *p++);
|
|
y += 4 * c;
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 4 * c;
|
|
w += 2 * c;
|
|
c = *(cp - *p);
|
|
x += 4 * c;
|
|
y += 4 * c;
|
|
w += 4 * c;
|
|
p += x_size - 3;
|
|
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += 9 * c;
|
|
w -= 3 * c;
|
|
c = *(cp - *p++);
|
|
y += 9 * c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y += 9 * c;
|
|
w += 3 * c;
|
|
|
|
if (y == 0)
|
|
z = 1000000.0;
|
|
else
|
|
z = ((float) x) / ((float) y);
|
|
if (z < 0.5) {
|
|
/* vertical */ a = 0;
|
|
b = 1;
|
|
} else {
|
|
if (z > 2.0) {
|
|
/* horizontal */ a = 1;
|
|
b = 0;
|
|
} else {
|
|
/* diagonal */ if (w > 0) {
|
|
a = -1;
|
|
b = 1;
|
|
} else {
|
|
a = 1;
|
|
b = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((m > r[(i + a) * x_size + j + b]) &&
|
|
(m >= r[(i - a) * x_size + j - b]) &&
|
|
(m > r[(i + (2 * a)) * x_size + j + (2 * b)]) &&
|
|
(m >= r[(i - (2 * a)) * x_size + j - (2 * b)]))
|
|
mid[i * x_size + j] = 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_edges_small(uchar *in, char *r, uchar *mid, uchar *bp, int max_no,
|
|
int x_size, int y_size) {
|
|
float z;
|
|
int do_symmetry, i, j, m, n, a, b, x, y, w;
|
|
uchar c, *p, *cp;
|
|
|
|
susan_wccmemset(r, 0, x_size * y_size);
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 1; i < y_size - 1; i++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (j = 1; j < x_size - 1; j++) {
|
|
n = 100;
|
|
p = in + (i - 1) * x_size + j - 1;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 2;
|
|
|
|
n += *(cp - *p);
|
|
p += 2;
|
|
n += *(cp - *p);
|
|
p += x_size - 2;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
|
|
if (n <= max_no)
|
|
r[i * x_size + j] = max_no - n;
|
|
}
|
|
}
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 2; i < y_size - 2; i++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (j = 2; j < x_size - 2; j++) {
|
|
if (r[i * x_size + j] > 0) {
|
|
m = r[i * x_size + j];
|
|
n = max_no - m;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
if (n > 250) {
|
|
p = in + (i - 1) * x_size + j - 1;
|
|
x = 0;
|
|
y = 0;
|
|
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y -= c;
|
|
c = *(cp - *p++);
|
|
y -= c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y -= c;
|
|
p += x_size - 2;
|
|
|
|
c = *(cp - *p);
|
|
x -= c;
|
|
p += 2;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
p += x_size - 2;
|
|
|
|
c = *(cp - *p++);
|
|
x -= c;
|
|
y += c;
|
|
c = *(cp - *p++);
|
|
y += c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y += c;
|
|
|
|
z = susan_sqrtf((float) ((x * x) + (y * y)));
|
|
if (z > (0.4 * (float) n)) { /* 0.6 */
|
|
do_symmetry = 0;
|
|
if (x == 0)
|
|
z = 1000000.0;
|
|
else
|
|
z = ((float) y) / ((float) x);
|
|
if (z < 0) {
|
|
z = -z;
|
|
w = -1;
|
|
} else
|
|
w = 1;
|
|
if (z < 0.5) {
|
|
/* vert_edge */ a = 0;
|
|
b = 1;
|
|
} else {
|
|
if (z > 2.0) {
|
|
/* hor_edge */ a = 1;
|
|
b = 0;
|
|
} else {
|
|
/* diag_edge */ if (w > 0) {
|
|
a = 1;
|
|
b = 1;
|
|
} else {
|
|
a = -1;
|
|
b = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((m > r[(i + a) * x_size + j + b]) &&
|
|
(m >= r[(i - a) * x_size + j - b]))
|
|
mid[i * x_size + j] = 1;
|
|
} else
|
|
do_symmetry = 1;
|
|
} else
|
|
do_symmetry = 1;
|
|
|
|
if (do_symmetry == 1) {
|
|
p = in + (i - 1) * x_size + j - 1;
|
|
x = 0;
|
|
y = 0;
|
|
w = 0;
|
|
|
|
/* | \
|
|
y -x- w
|
|
| \ */
|
|
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
w += c;
|
|
c = *(cp - *p++);
|
|
y += c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y += c;
|
|
w -= c;
|
|
p += x_size - 2;
|
|
|
|
c = *(cp - *p);
|
|
x += c;
|
|
p += 2;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
p += x_size - 2;
|
|
|
|
c = *(cp - *p++);
|
|
x += c;
|
|
y += c;
|
|
w -= c;
|
|
c = *(cp - *p++);
|
|
y += c;
|
|
c = *(cp - *p);
|
|
x += c;
|
|
y += c;
|
|
w += c;
|
|
|
|
if (y == 0)
|
|
z = 1000000.0;
|
|
else
|
|
z = ((float) x) / ((float) y);
|
|
if (z < 0.5) {
|
|
/* vertical */ a = 0;
|
|
b = 1;
|
|
} else {
|
|
if (z > 2.0) {
|
|
/* horizontal */ a = 1;
|
|
b = 0;
|
|
} else {
|
|
/* diagonal */ if (w > 0) {
|
|
a = -1;
|
|
b = 1;
|
|
} else {
|
|
a = 1;
|
|
b = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((m > r[(i + a) * x_size + j + b]) &&
|
|
(m >= r[(i - a) * x_size + j - b]))
|
|
mid[i * x_size + j] = 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_corner_draw(uchar *in, CORNER_LIST corner_list, int x_size,
|
|
int drawing_mode) {
|
|
uchar *p;
|
|
int n = 0;
|
|
|
|
__pragma_loopbound(0, 0);
|
|
while (corner_list[n].info != 7) {
|
|
if (drawing_mode == 0) {
|
|
p = in + (corner_list[n].y - 1) * x_size + corner_list[n].x - 1;
|
|
*p++ = 255;
|
|
*p++ = 255;
|
|
*p = 255;
|
|
p += x_size - 2;
|
|
*p++ = 255;
|
|
*p++ = 0;
|
|
*p = 255;
|
|
p += x_size - 2;
|
|
*p++ = 255;
|
|
*p++ = 255;
|
|
*p = 255;
|
|
n++;
|
|
} else {
|
|
p = in + corner_list[n].y * x_size + corner_list[n].x;
|
|
*p = 0;
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
susan_corners(uchar *in, char *r, uchar *bp, int max_no,
|
|
CORNER_LIST corner_list, int x_size, int y_size) {
|
|
int n, x, y, sq, xx, yy, i, j;
|
|
float divide;
|
|
uchar c, *p, *cp;
|
|
char *cgx, *cgy;
|
|
|
|
susan_wccmemset(r, 0, x_size * y_size);
|
|
|
|
cgx = (char *) susan_wccmalloc(x_size * y_size);
|
|
cgy = (char *) susan_wccmalloc(x_size * y_size);
|
|
|
|
__pragma_loopbound(85, 85);
|
|
for (i = 5; i < y_size - 5; i++) {
|
|
__pragma_loopbound(66, 66);
|
|
for (j = 5; j < x_size - 5; j++) {
|
|
n = 100;
|
|
p = in + (i - 3) * x_size + j - 1;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 3;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
if (n < max_no) { /* do this test early and often ONLY to save
|
|
wasted computation */
|
|
p += 2;
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p);
|
|
if (n < max_no) {
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p);
|
|
if (n < max_no) {
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n +=
|
|
*(cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n += *(
|
|
cp -
|
|
*p);
|
|
if (n <
|
|
max_no) {
|
|
p +=
|
|
x_size -
|
|
3;
|
|
|
|
n += *(
|
|
cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n += *(
|
|
cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n += *(
|
|
cp -
|
|
*p);
|
|
|
|
if (n <
|
|
max_no) {
|
|
x = 0;
|
|
y = 0;
|
|
p = in +
|
|
(i -
|
|
3) *
|
|
x_size +
|
|
j -
|
|
1;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
c;
|
|
y -=
|
|
3 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
y -=
|
|
3 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
c;
|
|
y -=
|
|
3 *
|
|
c;
|
|
p +=
|
|
x_size -
|
|
3;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
2 *
|
|
c;
|
|
y -=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
c;
|
|
y -=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
y -=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
c;
|
|
y -=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
2 *
|
|
c;
|
|
y -=
|
|
2 *
|
|
c;
|
|
p +=
|
|
x_size -
|
|
5;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
3 *
|
|
c;
|
|
y -=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
2 *
|
|
c;
|
|
y -=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
c;
|
|
y -=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
y -=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
c;
|
|
y -=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
2 *
|
|
c;
|
|
y -=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
3 *
|
|
c;
|
|
y -=
|
|
c;
|
|
p +=
|
|
x_size -
|
|
6;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
3 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x -=
|
|
c;
|
|
p +=
|
|
2;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
3 *
|
|
c;
|
|
p +=
|
|
x_size -
|
|
6;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
3 *
|
|
c;
|
|
y +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
2 *
|
|
c;
|
|
y +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
c;
|
|
y +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
y +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
c;
|
|
y +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
2 *
|
|
c;
|
|
y +=
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
3 *
|
|
c;
|
|
y +=
|
|
c;
|
|
p +=
|
|
x_size -
|
|
5;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
2 *
|
|
c;
|
|
y +=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
c;
|
|
y +=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
y +=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x +=
|
|
c;
|
|
y +=
|
|
2 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
2 *
|
|
c;
|
|
y +=
|
|
2 *
|
|
c;
|
|
p +=
|
|
x_size -
|
|
3;
|
|
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
x -=
|
|
c;
|
|
y +=
|
|
3 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p++);
|
|
y +=
|
|
3 *
|
|
c;
|
|
c = *(
|
|
cp -
|
|
*p);
|
|
x +=
|
|
c;
|
|
y +=
|
|
3 *
|
|
c;
|
|
|
|
xx =
|
|
x *
|
|
x;
|
|
yy =
|
|
y *
|
|
y;
|
|
sq =
|
|
xx +
|
|
yy;
|
|
if (sq >
|
|
((n *
|
|
n) /
|
|
2)) {
|
|
if (yy <
|
|
xx) {
|
|
divide =
|
|
(float)
|
|
y /
|
|
(float) abs(
|
|
x);
|
|
sq =
|
|
abs(x) /
|
|
x;
|
|
sq =
|
|
*(cp -
|
|
in[(i +
|
|
FTOI(
|
|
divide)) *
|
|
x_size +
|
|
j +
|
|
sq]) +
|
|
*(cp -
|
|
in[(i +
|
|
FTOI(
|
|
2 *
|
|
divide)) *
|
|
x_size +
|
|
j +
|
|
2 * sq]) +
|
|
*(cp -
|
|
in[(i +
|
|
FTOI(
|
|
3 *
|
|
divide)) *
|
|
x_size +
|
|
j +
|
|
3 * sq]);
|
|
} else {
|
|
divide =
|
|
(float)
|
|
x /
|
|
(float) abs(
|
|
y);
|
|
sq =
|
|
abs(y) /
|
|
y;
|
|
sq =
|
|
*(cp -
|
|
in[(i +
|
|
sq) *
|
|
x_size +
|
|
j +
|
|
FTOI(
|
|
divide)]) +
|
|
*(cp -
|
|
in[(i +
|
|
2 * sq) *
|
|
x_size +
|
|
j +
|
|
FTOI(
|
|
2 *
|
|
divide)]) +
|
|
*(cp -
|
|
in[(i +
|
|
3 * sq) *
|
|
x_size +
|
|
j +
|
|
FTOI(
|
|
3 *
|
|
divide)]);
|
|
}
|
|
|
|
if (sq >
|
|
290) {
|
|
r[i * x_size +
|
|
j] =
|
|
max_no -
|
|
n;
|
|
cgx[i * x_size +
|
|
j] =
|
|
(51 *
|
|
x) /
|
|
n;
|
|
cgy[i * x_size +
|
|
j] =
|
|
(51 *
|
|
y) /
|
|
n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* to locate the local maxima */
|
|
n = 0;
|
|
__pragma_loopbound(85, 85);
|
|
for (i = 5; i < y_size - 5; i++) {
|
|
__pragma_loopbound(66, 66);
|
|
for (j = 5; j < x_size - 5; j++) {
|
|
x = r[i * x_size + j];
|
|
if (x > 0) {
|
|
/* 5x5 mask */
|
|
#ifdef FIVE_SUPP
|
|
if ((x > r[(i - 1) * x_size + j + 2]) &&
|
|
(x > r[(i) *x_size + j + 1]) &&
|
|
(x > r[(i) *x_size + j + 2]) &&
|
|
(x > r[(i + 1) * x_size + j - 1]) &&
|
|
(x > r[(i + 1) * x_size + j]) &&
|
|
(x > r[(i + 1) * x_size + j + 1]) &&
|
|
(x > r[(i + 1) * x_size + j + 2]) &&
|
|
(x > r[(i + 2) * x_size + j - 2]) &&
|
|
(x > r[(i + 2) * x_size + j - 1]) &&
|
|
(x > r[(i + 2) * x_size + j]) &&
|
|
(x > r[(i + 2) * x_size + j + 1]) &&
|
|
(x > r[(i + 2) * x_size + j + 2]) &&
|
|
(x >= r[(i - 2) * x_size + j - 2]) &&
|
|
(x >= r[(i - 2) * x_size + j - 1]) &&
|
|
(x >= r[(i - 2) * x_size + j]) &&
|
|
(x >= r[(i - 2) * x_size + j + 1]) &&
|
|
(x >= r[(i - 2) * x_size + j + 2]) &&
|
|
(x >= r[(i - 1) * x_size + j - 2]) &&
|
|
(x >= r[(i - 1) * x_size + j - 1]) &&
|
|
(x >= r[(i - 1) * x_size + j]) &&
|
|
(x >= r[(i - 1) * x_size + j + 1]) &&
|
|
(x >= r[(i) *x_size + j - 2]) &&
|
|
(x >= r[(i) *x_size + j - 1]) &&
|
|
(x >= r[(i + 1) * x_size + j - 2]))
|
|
#endif
|
|
#ifdef SEVEN_SUPP
|
|
if ((x > r[(i - 3) * x_size + j - 3]) &&
|
|
(x > r[(i - 3) * x_size + j - 2]) &&
|
|
(x > r[(i - 3) * x_size + j - 1]) &&
|
|
(x > r[(i - 3) * x_size + j]) &&
|
|
(x > r[(i - 3) * x_size + j + 1]) &&
|
|
(x > r[(i - 3) * x_size + j + 2]) &&
|
|
(x > r[(i - 3) * x_size + j + 3]) &&
|
|
|
|
(x > r[(i - 2) * x_size + j - 3]) &&
|
|
(x > r[(i - 2) * x_size + j - 2]) &&
|
|
(x > r[(i - 2) * x_size + j - 1]) &&
|
|
(x > r[(i - 2) * x_size + j]) &&
|
|
(x > r[(i - 2) * x_size + j + 1]) &&
|
|
(x > r[(i - 2) * x_size + j + 2]) &&
|
|
(x > r[(i - 2) * x_size + j + 3]) &&
|
|
|
|
(x > r[(i - 1) * x_size + j - 3]) &&
|
|
(x > r[(i - 1) * x_size + j - 2]) &&
|
|
(x > r[(i - 1) * x_size + j - 1]) &&
|
|
(x > r[(i - 1) * x_size + j]) &&
|
|
(x > r[(i - 1) * x_size + j + 1]) &&
|
|
(x > r[(i - 1) * x_size + j + 2]) &&
|
|
(x > r[(i - 1) * x_size + j + 3]) &&
|
|
|
|
(x > r[(i) *x_size + j - 3]) &&
|
|
(x > r[(i) *x_size + j - 2]) &&
|
|
(x > r[(i) *x_size + j - 1]) &&
|
|
(x >= r[(i) *x_size + j + 1]) &&
|
|
(x >= r[(i) *x_size + j + 2]) &&
|
|
(x >= r[(i) *x_size + j + 3]) &&
|
|
|
|
(x >= r[(i + 1) * x_size + j - 3]) &&
|
|
(x >= r[(i + 1) * x_size + j - 2]) &&
|
|
(x >= r[(i + 1) * x_size + j - 1]) &&
|
|
(x >= r[(i + 1) * x_size + j]) &&
|
|
(x >= r[(i + 1) * x_size + j + 1]) &&
|
|
(x >= r[(i + 1) * x_size + j + 2]) &&
|
|
(x >= r[(i + 1) * x_size + j + 3]) &&
|
|
|
|
(x >= r[(i + 2) * x_size + j - 3]) &&
|
|
(x >= r[(i + 2) * x_size + j - 2]) &&
|
|
(x >= r[(i + 2) * x_size + j - 1]) &&
|
|
(x >= r[(i + 2) * x_size + j]) &&
|
|
(x >= r[(i + 2) * x_size + j + 1]) &&
|
|
(x >= r[(i + 2) * x_size + j + 2]) &&
|
|
(x >= r[(i + 2) * x_size + j + 3]) &&
|
|
|
|
(x >= r[(i + 3) * x_size + j - 3]) &&
|
|
(x >= r[(i + 3) * x_size + j - 2]) &&
|
|
(x >= r[(i + 3) * x_size + j - 1]) &&
|
|
(x >= r[(i + 3) * x_size + j]) &&
|
|
(x >= r[(i + 3) * x_size + j + 1]) &&
|
|
(x >= r[(i + 3) * x_size + j + 2]) &&
|
|
(x >= r[(i + 3) * x_size + j + 3]))
|
|
#endif
|
|
{
|
|
corner_list[n].info = 0;
|
|
corner_list[n].x = j;
|
|
corner_list[n].y = i;
|
|
corner_list[n].dx = cgx[i * x_size + j];
|
|
corner_list[n].dy = cgy[i * x_size + j];
|
|
corner_list[n].I = in[i * x_size + j];
|
|
n++;
|
|
if (n == MAX_CORNERS) {
|
|
/* "Too many corners." */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
corner_list[n].info = 7;
|
|
}
|
|
|
|
void
|
|
susan_corners_quick(uchar *in, char *r, uchar *bp, int max_no,
|
|
CORNER_LIST corner_list, int x_size, int y_size) {
|
|
int n, x, y, i, j;
|
|
uchar *p, *cp;
|
|
|
|
susan_wccmemset(r, 0, x_size * y_size);
|
|
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 7; i < y_size - 7; i++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (j = 7; j < x_size - 7; j++) {
|
|
n = 100;
|
|
p = in + (i - 3) * x_size + j - 1;
|
|
cp = bp + in[i * x_size + j];
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 3;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p++);
|
|
n += *(cp - *p);
|
|
if (n < max_no) {
|
|
p += 2;
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p);
|
|
if (n < max_no) {
|
|
p += x_size - 6;
|
|
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p);
|
|
if (n < max_no) {
|
|
p += x_size - 5;
|
|
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp - *p++);
|
|
if (n < max_no) {
|
|
n += *(cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n +=
|
|
*(cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n += *(
|
|
cp -
|
|
*p);
|
|
if (n <
|
|
max_no) {
|
|
p +=
|
|
x_size -
|
|
3;
|
|
|
|
n += *(
|
|
cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n += *(
|
|
cp -
|
|
*p++);
|
|
if (n <
|
|
max_no) {
|
|
n += *(
|
|
cp -
|
|
*p);
|
|
|
|
if (n <
|
|
max_no)
|
|
r[i * x_size +
|
|
j] =
|
|
max_no -
|
|
n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* to locate the local maxima */
|
|
n = 0;
|
|
__pragma_loopbound(0, 0);
|
|
for (i = 7; i < y_size - 7; i++) {
|
|
__pragma_loopbound(0, 0);
|
|
for (j = 7; j < x_size - 7; j++) {
|
|
x = r[i * x_size + j];
|
|
if (x > 0) {
|
|
/* 5x5 mask */
|
|
#ifdef FIVE_SUPP
|
|
if ((x > r[(i - 1) * x_size + j + 2]) &&
|
|
(x > r[(i) *x_size + j + 1]) &&
|
|
(x > r[(i) *x_size + j + 2]) &&
|
|
(x > r[(i + 1) * x_size + j - 1]) &&
|
|
(x > r[(i + 1) * x_size + j]) &&
|
|
(x > r[(i + 1) * x_size + j + 1]) &&
|
|
(x > r[(i + 1) * x_size + j + 2]) &&
|
|
(x > r[(i + 2) * x_size + j - 2]) &&
|
|
(x > r[(i + 2) * x_size + j - 1]) &&
|
|
(x > r[(i + 2) * x_size + j]) &&
|
|
(x > r[(i + 2) * x_size + j + 1]) &&
|
|
(x > r[(i + 2) * x_size + j + 2]) &&
|
|
(x >= r[(i - 2) * x_size + j - 2]) &&
|
|
(x >= r[(i - 2) * x_size + j - 1]) &&
|
|
(x >= r[(i - 2) * x_size + j]) &&
|
|
(x >= r[(i - 2) * x_size + j + 1]) &&
|
|
(x >= r[(i - 2) * x_size + j + 2]) &&
|
|
(x >= r[(i - 1) * x_size + j - 2]) &&
|
|
(x >= r[(i - 1) * x_size + j - 1]) &&
|
|
(x >= r[(i - 1) * x_size + j]) &&
|
|
(x >= r[(i - 1) * x_size + j + 1]) &&
|
|
(x >= r[(i) *x_size + j - 2]) &&
|
|
(x >= r[(i) *x_size + j - 1]) &&
|
|
(x >= r[(i + 1) * x_size + j - 2]))
|
|
#endif
|
|
#ifdef SEVEN_SUPP
|
|
if ((x > r[(i - 3) * x_size + j - 3]) &&
|
|
(x > r[(i - 3) * x_size + j - 2]) &&
|
|
(x > r[(i - 3) * x_size + j - 1]) &&
|
|
(x > r[(i - 3) * x_size + j]) &&
|
|
(x > r[(i - 3) * x_size + j + 1]) &&
|
|
(x > r[(i - 3) * x_size + j + 2]) &&
|
|
(x > r[(i - 3) * x_size + j + 3]) &&
|
|
|
|
(x > r[(i - 2) * x_size + j - 3]) &&
|
|
(x > r[(i - 2) * x_size + j - 2]) &&
|
|
(x > r[(i - 2) * x_size + j - 1]) &&
|
|
(x > r[(i - 2) * x_size + j]) &&
|
|
(x > r[(i - 2) * x_size + j + 1]) &&
|
|
(x > r[(i - 2) * x_size + j + 2]) &&
|
|
(x > r[(i - 2) * x_size + j + 3]) &&
|
|
|
|
(x > r[(i - 1) * x_size + j - 3]) &&
|
|
(x > r[(i - 1) * x_size + j - 2]) &&
|
|
(x > r[(i - 1) * x_size + j - 1]) &&
|
|
(x > r[(i - 1) * x_size + j]) &&
|
|
(x > r[(i - 1) * x_size + j + 1]) &&
|
|
(x > r[(i - 1) * x_size + j + 2]) &&
|
|
(x > r[(i - 1) * x_size + j + 3]) &&
|
|
|
|
(x > r[(i) *x_size + j - 3]) &&
|
|
(x > r[(i) *x_size + j - 2]) &&
|
|
(x > r[(i) *x_size + j - 1]) &&
|
|
(x >= r[(i) *x_size + j + 1]) &&
|
|
(x >= r[(i) *x_size + j + 2]) &&
|
|
(x >= r[(i) *x_size + j + 3]) &&
|
|
|
|
(x >= r[(i + 1) * x_size + j - 3]) &&
|
|
(x >= r[(i + 1) * x_size + j - 2]) &&
|
|
(x >= r[(i + 1) * x_size + j - 1]) &&
|
|
(x >= r[(i + 1) * x_size + j]) &&
|
|
(x >= r[(i + 1) * x_size + j + 1]) &&
|
|
(x >= r[(i + 1) * x_size + j + 2]) &&
|
|
(x >= r[(i + 1) * x_size + j + 3]) &&
|
|
|
|
(x >= r[(i + 2) * x_size + j - 3]) &&
|
|
(x >= r[(i + 2) * x_size + j - 2]) &&
|
|
(x >= r[(i + 2) * x_size + j - 1]) &&
|
|
(x >= r[(i + 2) * x_size + j]) &&
|
|
(x >= r[(i + 2) * x_size + j + 1]) &&
|
|
(x >= r[(i + 2) * x_size + j + 2]) &&
|
|
(x >= r[(i + 2) * x_size + j + 3]) &&
|
|
|
|
(x >= r[(i + 3) * x_size + j - 3]) &&
|
|
(x >= r[(i + 3) * x_size + j - 2]) &&
|
|
(x >= r[(i + 3) * x_size + j - 1]) &&
|
|
(x >= r[(i + 3) * x_size + j]) &&
|
|
(x >= r[(i + 3) * x_size + j + 1]) &&
|
|
(x >= r[(i + 3) * x_size + j + 2]) &&
|
|
(x >= r[(i + 3) * x_size + j + 3]))
|
|
#endif
|
|
{
|
|
corner_list[n].info = 0;
|
|
corner_list[n].x = j;
|
|
corner_list[n].y = i;
|
|
x = in[(i - 2) * x_size + j - 2] +
|
|
in[(i - 2) * x_size + j - 1] +
|
|
in[(i - 2) * x_size + j] +
|
|
in[(i - 2) * x_size + j + 1] +
|
|
in[(i - 2) * x_size + j + 2] +
|
|
in[(i - 1) * x_size + j - 2] +
|
|
in[(i - 1) * x_size + j - 1] +
|
|
in[(i - 1) * x_size + j] +
|
|
in[(i - 1) * x_size + j + 1] +
|
|
in[(i - 1) * x_size + j + 2] +
|
|
in[(i) *x_size + j - 2] + in[(i) *x_size + j - 1] +
|
|
in[(i) *x_size + j] + in[(i) *x_size + j + 1] +
|
|
in[(i) *x_size + j + 2] +
|
|
in[(i + 1) * x_size + j - 2] +
|
|
in[(i + 1) * x_size + j - 1] +
|
|
in[(i + 1) * x_size + j] +
|
|
in[(i + 1) * x_size + j + 1] +
|
|
in[(i + 1) * x_size + j + 2] +
|
|
in[(i + 2) * x_size + j - 2] +
|
|
in[(i + 2) * x_size + j - 1] +
|
|
in[(i + 2) * x_size + j] +
|
|
in[(i + 2) * x_size + j + 1] +
|
|
in[(i + 2) * x_size + j + 2];
|
|
|
|
corner_list[n].I = x / 25;
|
|
/*corner_list[ n ].I=in[ i*x_size+j ];*/
|
|
x = in[(i - 2) * x_size + j + 2] +
|
|
in[(i - 1) * x_size + j + 2] +
|
|
in[(i) *x_size + j + 2] +
|
|
in[(i + 1) * x_size + j + 2] +
|
|
in[(i + 2) * x_size + j + 2] -
|
|
(in[(i - 2) * x_size + j - 2] +
|
|
in[(i - 1) * x_size + j - 2] +
|
|
in[(i) *x_size + j - 2] +
|
|
in[(i + 1) * x_size + j - 2] +
|
|
in[(i + 2) * x_size + j - 2]);
|
|
x += x + in[(i - 2) * x_size + j + 1] +
|
|
in[(i - 1) * x_size + j + 1] +
|
|
in[(i) *x_size + j + 1] +
|
|
in[(i + 1) * x_size + j + 1] +
|
|
in[(i + 2) * x_size + j + 1] -
|
|
(in[(i - 2) * x_size + j - 1] +
|
|
in[(i - 1) * x_size + j - 1] +
|
|
in[(i) *x_size + j - 1] +
|
|
in[(i + 1) * x_size + j - 1] +
|
|
in[(i + 2) * x_size + j - 1]);
|
|
|
|
y = in[(i + 2) * x_size + j - 2] +
|
|
in[(i + 2) * x_size + j - 1] +
|
|
in[(i + 2) * x_size + j] +
|
|
in[(i + 2) * x_size + j + 1] +
|
|
in[(i + 2) * x_size + j + 2] -
|
|
(in[(i - 2) * x_size + j - 2] +
|
|
in[(i - 2) * x_size + j - 1] +
|
|
in[(i - 2) * x_size + j] +
|
|
in[(i - 2) * x_size + j + 1] +
|
|
in[(i - 2) * x_size + j + 2]);
|
|
y += y + in[(i + 1) * x_size + j - 2] +
|
|
in[(i + 1) * x_size + j - 1] +
|
|
in[(i + 1) * x_size + j] +
|
|
in[(i + 1) * x_size + j + 1] +
|
|
in[(i + 1) * x_size + j + 2] -
|
|
(in[(i - 1) * x_size + j - 2] +
|
|
in[(i - 1) * x_size + j - 1] +
|
|
in[(i - 1) * x_size + j] +
|
|
in[(i - 1) * x_size + j + 1] +
|
|
in[(i - 1) * x_size + j + 2]);
|
|
corner_list[n].dx = x / 15;
|
|
corner_list[n].dy = y / 15;
|
|
n++;
|
|
if (n == MAX_CORNERS) {
|
|
/* "Too many corners." */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
corner_list[n].info = 7;
|
|
}
|
|
|
|
void
|
|
susan_call_susan(struct wccFILE *inputFile, int mode) {
|
|
uchar *in, *bp, *mid;
|
|
int x_size, y_size;
|
|
char *r;
|
|
CORNER_LIST corner_list;
|
|
|
|
susan_get_image(inputFile, &in, &x_size, &y_size);
|
|
|
|
if (susan_dt < 0)
|
|
susan_three_by_three = 1;
|
|
if ((susan_principle_conf == 1) && (mode == 0))
|
|
mode = 1;
|
|
|
|
switch (mode) {
|
|
case 0:
|
|
/* {{{ smoothing */
|
|
|
|
susan_setup_brightness_lut(&bp, susan_bt, 2);
|
|
susan_smoothing(susan_three_by_three, in, susan_dt, x_size, y_size, bp);
|
|
|
|
break;
|
|
case 1:
|
|
/* {{{ edges */
|
|
|
|
r = (char *) susan_wccmalloc(x_size * y_size);
|
|
susan_setup_brightness_lut(&bp, susan_bt, 6);
|
|
|
|
if (susan_principle_conf) {
|
|
if (susan_three_by_three)
|
|
susan_principle_small(in, r, bp, susan_max_no_edges, x_size,
|
|
y_size);
|
|
else
|
|
susan_principle(in, r, bp, susan_max_no_edges, x_size, y_size);
|
|
susan_int_to_uchar(r, in, x_size * y_size);
|
|
} else {
|
|
mid = (uchar *) susan_wccmalloc(x_size * y_size);
|
|
susan_wccmemset(mid, 100,
|
|
x_size * y_size); /* note not set to zero */
|
|
|
|
if (susan_three_by_three)
|
|
susan_edges_small(in, r, mid, bp, susan_max_no_edges, x_size,
|
|
y_size);
|
|
else
|
|
susan_edges(in, r, mid, bp, susan_max_no_edges, x_size, y_size);
|
|
if (susan_thin_post_proc)
|
|
susan_thin(r, mid, x_size, y_size);
|
|
susan_edge_draw(in, mid, x_size, y_size, susan_drawing_mode);
|
|
}
|
|
|
|
break;
|
|
case 2:
|
|
/* {{{ corners */
|
|
|
|
r = (char *) susan_wccmalloc(x_size * y_size);
|
|
susan_setup_brightness_lut(&bp, susan_bt, 6);
|
|
|
|
if (susan_principle_conf) {
|
|
susan_principle(in, r, bp, susan_max_no_corners, x_size, y_size);
|
|
susan_int_to_uchar(r, in, x_size * y_size);
|
|
} else {
|
|
if (susan_susan_quick)
|
|
susan_corners_quick(in, r, bp, susan_max_no_corners,
|
|
corner_list, x_size, y_size);
|
|
else
|
|
susan_corners(in, r, bp, susan_max_no_corners, corner_list,
|
|
x_size, y_size);
|
|
susan_corner_draw(in, corner_list, x_size, susan_drawing_mode);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
susan_put_image(x_size, y_size);
|
|
}
|
|
|
|
void
|
|
susan_init(void) {
|
|
volatile int a = 0;
|
|
susan_file.data = susan_input;
|
|
susan_file.size = 7292;
|
|
susan_file.size += a;
|
|
susan_file.cur_pos = 0;
|
|
susan_file.cur_pos += a;
|
|
|
|
susan_dt = 4.0;
|
|
susan_dt += a;
|
|
susan_bt = 20;
|
|
susan_bt += a;
|
|
susan_principle_conf = 0;
|
|
susan_principle_conf += a;
|
|
susan_thin_post_proc = 1;
|
|
susan_thin_post_proc += a;
|
|
susan_three_by_three = 0;
|
|
susan_three_by_three += a;
|
|
susan_drawing_mode = 0;
|
|
susan_drawing_mode += a;
|
|
susan_susan_quick = 0;
|
|
susan_susan_quick += a;
|
|
susan_max_no_corners = 50;
|
|
susan_max_no_corners += a;
|
|
susan_max_no_edges = 50;
|
|
susan_max_no_edges += a;
|
|
|
|
// mode=0; /* Smoothing mode */
|
|
// mode=1; /* Edges mode */
|
|
// mode=2; /* Corners mode */
|
|
|
|
// principle=1; /* Output initial enhancement image only; corners or edges
|
|
// mode (default is edges mode) */ thin_post_proc=0; /* No post-processing
|
|
// on the binary edge map (runs much faster); edges mode */ drawing_mode=1;
|
|
// /* Mark corners/edges with single black points instead of black with
|
|
// white border; corners or edges mode */ three_by_three=1; /* Use flat 3x3
|
|
// mask, edges or smoothing mode */ susan_quick=1; /* Use faster (and
|
|
// usually stabler) corner mode; edge-like corner suppression not carried
|
|
// out; corners mode */ dt=10.0; /* Distance threshold, smoothing mode,
|
|
// (default=4) */ bt=50; /* Brightness threshold, all modes, (default=20) */
|
|
}
|
|
|
|
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
|
|
susan_main(void) {
|
|
susan_call_susan(&susan_file, 0);
|
|
susan_wccfreeall();
|
|
susan_call_susan(&susan_file, 1);
|
|
susan_wccfreeall();
|
|
susan_call_susan(&susan_file, 2);
|
|
susan_wccfreeall();
|
|
}
|
|
|
|
int
|
|
susan_return(void) {
|
|
return 0;
|
|
}
|
|
|
|
__attribute__((noinline)) __attribute__((export_name("main"))) int
|
|
main(void) {
|
|
susan_init();
|
|
susan_main();
|
|
|
|
return susan_return();
|
|
}
|