#include <math.h>
#include <stdio.h>
#include "myvec.h"
#include "imatrix.h"
#include "ETF.h"
#include "fdog.h"
#include "stackmem.h"
#ifdef MEMDEBUG
#include "mnemosyne.h"
#endif
extern int debug;
#define PI 3.141592653589793
#define ABS(x) ( ((x)>0) ? (x) : (-(x)) )
#define round(x) ((int) ((x) + 0.5))
double gauss(double x, double mean, double sigma)
{
return ( exp( (-(x-mean)*(x-mean)) / (2*sigma*sigma) ) / sqrt(PI * 2.0 * sigma*sigma) );
}
myvec *MakeGaussianVector(double sigma)
{
myvec *GAU;
int i, j;
double threshold = 0.001;
#ifdef NEVER
for (i = 1; gauss((double)i, 0.0, sigma) > threshold; i++);
#else
i = 0;
while(1) {
i++;
if ( gauss((double)i, 0.0, sigma) < threshold )
break;
}
#endif
GAU = myvec_new(i+1);
GAU->p[0] = gauss((double)0.0, 0.0, sigma);
for (j = 1; j < myvec_getMax(GAU); j++) GAU->p[j] = gauss((double)j, 0.0, sigma);
if (debug) fprintf(stderr, "MakeGaussianVector(%f)[%d]: %f\n", sigma, myvec_getMax(GAU), myvec_crc(GAU));
return GAU;
}
void GetDirectionalDoG(imatrix *image, ETF *e, mymatrix *dog, myvec *GAU1, myvec *GAU2, double tau)
{
/*myvec *vn = myvec_new(2);*/
double vn[2] = {0.0, 0.0};
double x, y, d_x, d_y;
double weight1, weight2, w_sum1, sum1, sum2, w_sum2;
int s;
int x1, y1;
int i, j;
int dd;
double val;
int half_w1, half_w2;
int image_x, image_y;
half_w1 = myvec_getMax(GAU1)-1;
half_w2 = myvec_getMax(GAU2)-1;
image_x = imatrix_getRow(image);
image_y = imatrix_getCol(image);
if (debug) fprintf(stderr, "GetDirectionalDoG: image %d e %f dog %f\n", imatrix_crc(image), ETF_crc(e), mymatrix_crc(dog));
for (i = 0; i < image_x; i++) {
for (j = 0; j < image_y; j++) {
sum1 = sum2 = 0.0;
w_sum1 = w_sum2 = 0.0;
weight1 = weight2 = 0.0;
vn[0] = -e->p[i][j].ty;
vn[1] = e->p[i][j].tx;
if (vn[0] == 0.0 && vn[1] == 0.0) {
sum1 = 255.0;
sum2 = 255.0;
dog->p[i][j] = sum1 - tau * sum2;
continue;
}
d_x = i; d_y = j;
/* ////////////////////////////////// */
for (s = -half_w2; s <= half_w2; s++) {
/* ////////////////// */
x = d_x + vn[0] * s;
y = d_y + vn[1] * s;
/* /////////////////////////////////////////////// */
if (x > (double)image_x-1 || x < 0.0 || y > (double)image_y-1 || y < 0.0)
continue;
x1 = round(x); if (x1 < 0) x1 = 0; if (x1 > image_x-1) x1 = image_x-1;
y1 = round(y); if (y1 < 0) y1 = 0; if (y1 > image_y-1) y1 = image_y-1;
val = image->p[x1][y1];
/* /////////////////////////////////////////////////// */
dd = ABS(s);
if (dd > half_w1) weight1 = 0.0;
else weight1 = GAU1->p[dd];
/* //////////////////////////// */
sum1 += val * weight1;
w_sum1 += weight1;
/* /////////////////////////////////////////////// */
weight2 = GAU2->p[dd];
sum2 += val * weight2;
w_sum2 += weight2;
}
/* /////////////////// */
sum1 /= w_sum1;
sum2 /= w_sum2;
/* //////////////////////////////// */
dog->p[i][j] = sum1 - tau * sum2;
}
}
release(vn);
}
void GetFlowDoG(ETF *e, mymatrix *dog, mymatrix *tmp, myvec *GAU3)
{
myvec *vt = myvec_new(2);
double x, y, d_x, d_y;
double weight1, w_sum1, sum1;
int i_x, i_y, k;
int x1, y1;
double val;
int i, j;
int image_x = mymatrix_getRow(dog);
int image_y = mymatrix_getCol(dog);
int half_l;
double step_size = 1.0;
/* int flow_DOG_sign = 0; */
half_l = myvec_getMax(GAU3)-1;
for (i = 0; i < image_x; i++) {
for (j = 0; j < image_y; j++) {
sum1 = 0.0;
w_sum1 = 0.0;
weight1 = 0.0;
/* /////////////////////////// */
val = dog->p[i][j];
weight1 = GAU3->p[0];
sum1 = val * weight1;
w_sum1 += weight1;
/* ////////////////////////////////////////// */
d_x = (double)i; d_y = (double)j;
i_x = i; i_y = j;
/* ////////////////////// */
for (k = 0; k < half_l; k++) {
vt->p[0] = e->p[i_x][i_y].tx;
vt->p[1] = e->p[i_x][i_y].ty;
if (vt->p[0] == 0.0 && vt->p[1] == 0.0) break;
x = d_x;
y = d_y;
/* /////////////////////////////////////////////// */
if (x > (double)image_x-1 || x < 0.0 || y > (double)image_y-1 || y < 0.0) break;
x1 = round(x); if (x1 < 0) x1 = 0; if (x1 > image_x-1) x1 = image_x-1;
y1 = round(y); if (y1 < 0) y1 = 0; if (y1 > image_y-1) y1 = image_y-1;
val = dog->p[x1][y1];
/* //////////////////////// */
weight1 = GAU3->p[k];
/* ////////////// */
sum1 += val * weight1;
w_sum1 += weight1;
/* /////////////////////////////////// */
d_x += vt->p[0] * step_size;
d_y += vt->p[1] * step_size;
/* /////////////////////////////////// */
i_x = round(d_x);
i_y = round(d_y);
if (d_x < 0 || d_x > image_x-1 || d_y < 0 || d_y > image_y-1) break;
/* /////////////////// */
}
/* ////////////////////////////////////////// */
d_x = (double)i; d_y = (double)j;
i_x = i; i_y = j;
for (k = 0; k < half_l; k++) {
vt->p[0] = -e->p[i_x][i_y].tx;
vt->p[1] = -e->p[i_x][i_y].ty;
if (vt->p[0] == 0.0 && vt->p[1] == 0.0) break;
x = d_x;
y = d_y;
/* /////////////////////////////////////////////// */
if (x > (double)image_x-1 || x < 0.0 || y > (double)image_y-1 || y < 0.0) break;
x1 = round(x); if (x1 < 0) x1 = 0; if (x1 > image_x-1) x1 = image_x-1;
y1 = round(y); if (y1 < 0) y1 = 0; if (y1 > image_y-1) y1 = image_y-1;
val = dog->p[x1][y1];
/* //////////////////////// */
weight1 = GAU3->p[k];
/* ////////////// */
sum1 += val * weight1;
w_sum1 += weight1;
/* /////////////////////////////////// */
d_x += vt->p[0] * step_size;
d_y += vt->p[1] * step_size;
/* /////////////////////////////////// */
i_x = round(d_x);
i_y = round(d_y);
if (d_x < 0 || d_x > image_x-1 || d_y < 0 || d_y > image_y-1) break;
/* /////////////////// */
}
/* ////////////////////////////////// */
sum1 /= w_sum1;
/* //////////////////////////////// */
if (sum1 > 0) tmp->p[i][j] = 1.0;
else tmp->p[i][j] = 1.0 + tanh(sum1);
}
}
release(vt);
}
void GetFDoG(imatrix *image, ETF *e, double sigma, double sigma3, double tau)
{
int i, j;
int image_x = imatrix_getRow(image);
int image_y = imatrix_getCol(image);
myvec *GAU1, *GAU2, *GAU3;
int half_w1, half_w2, half_l;
mymatrix *tmp;
mymatrix *dog;
if (debug) fprintf(stderr, "GetFDoG entry e %f\n", ETF_crc(e));
GAU1 = MakeGaussianVector(sigma);
GAU2 = MakeGaussianVector(sigma*1.6);
if (debug) fprintf(stderr, "Gaussian1 %f\n", myvec_crc(GAU1));
if (debug) fprintf(stderr, "Gaussian2 %f\n", myvec_crc(GAU2));
half_w1 = myvec_getMax(GAU1)-1;
half_w2 = myvec_getMax(GAU2)-1;
GAU3 = MakeGaussianVector(sigma3);
if (debug) fprintf(stderr, "Gaussian3 %f\n", myvec_crc(GAU3));
half_l = myvec_getMax(GAU3)-1;
tmp = mymatrix_new(image_x, image_y);
dog = mymatrix_new(image_x, image_y);
GetDirectionalDoG(image, e, dog, GAU1, GAU2, tau);
if (debug) fprintf(stderr, "GetDirectionalDoG image %d\n", imatrix_crc(image));
if (debug) fprintf(stderr, "GetDirectionalDoG e %f\n", ETF_crc(e));
if (debug) fprintf(stderr, "GetDirectionalDoG dog %f\n", mymatrix_crc(dog));
GetFlowDoG(e, dog, tmp, GAU3);
if (debug) fprintf(stderr, "GetFlowDoG e %f\n", ETF_crc(e));
if (debug) fprintf(stderr, "GetFlowDoG dog %f\n", mymatrix_crc(dog));
if (debug) fprintf(stderr, "GetFlowDoG tmp %f\n", mymatrix_crc(tmp));
for (i = 0; i < image_x; i++) {
for (j = 0; j < image_y; j++) image->p[i][j] = round(tmp->p[i][j] * 255.);
}
release(GAU1);
}
void GaussSmoothSep(imatrix *image, double sigma) /* NOT USED ??? */
{
int i, j;
double g, max_g, min_g;
int s, t;
int x, y;
double weight, w_sum;
int image_x = imatrix_getRow(image);
int image_y = imatrix_getCol(image);
myvec *GAU1;
int half;
mymatrix *tmp;
/* int MAX_GRADIENT = -1; */
GAU1 = MakeGaussianVector(sigma);
half = myvec_getMax(GAU1)-1;
tmp = mymatrix_new(image_x, image_y);
max_g = -1; min_g = 10000000;
for (j = 0; j < image_y; j++) {
for (i = 0; i < image_x; i++) {
g = 0.0; weight = w_sum = 0.0;
for (s = -half; s <= half; s++) {
x = i+s; y = j;
if (x > image_x-1) x = image_x-1; else if (x < 0) x = 0;
if (y > image_y-1) y = image_y-1; else if (y < 0) y = 0;
weight = GAU1->p[ABS(s)];
g += weight * image->p[x][y];
w_sum += weight;
}
g /= w_sum;
if (g > max_g) max_g = g;
if (g < min_g) min_g = g;
tmp->p[i][j] = g;
}
}
for (j = 0; j < image_y; j++) {
for (i = 0; i < image_x; i++) {
g = 0.0;
weight = w_sum = 0.0;
for (t = -half; t <= half; t++) {
x = i; y = j+t;
if (x > image_x-1) x = image_x-1; else if (x < 0) x = 0;
if (y > image_y-1) y = image_y-1; else if (y < 0) y = 0;
weight = GAU1->p[ABS(t)];
g += weight * tmp->p[x][y];
w_sum += weight;
}
g /= w_sum;
if (g > max_g) max_g = g;
if (g < min_g) min_g = g;
image->p[i][j] = round(g);
}
}
release(GAU1);
/* TRACE("max_g = %f\n", max_g); */
/* TRACE("min_g = %f\n", min_g); */
}
#ifdef NEVER
void ConstructMergedImage(imatrix *image, imatrix *gray, imatrix *merged)
{
int x, y;
int image_x = imatrix_getRow(image), image_y = imatrix_getCol(image);
for (y = 0; y < image_y; y++) {
for (x = 0; x < image_x; x++) merged->p[x][y] = (gray->p[x][y] == 0 ? 0 : image->p[x][y]);
}
}
void ConstructMergedImageMult(imatrix *image, imatrix *gray, imatrix *merged) /* using multiplication */
{
int x, y;
double gray_val, line_darkness;
int image_x = imatrix_getRow(image), image_y = imatrix_getCol(image);
for (y = 0; y < image_y; y++) {
for (x = 0; x < image_x; x++) {
gray_val = image->p[x][y] / 255.0;
line_darkness = gray->p[x][y] / 255.0;
gray_val *= line_darkness;
merged->p[x][y] = round(gray_val * 255.0);
}
}
}
void Binarize(imatrix *image, double thres)
{
int i, j;
double val;
int image_x = imatrix_getRow(image), image_y = imatrix_getCol(image);
for (i = 0; i < image_x; i++) {
for (j = 0; j < image_y; j++) {
val = image->p[i][j] / 255.0;
image->p[i][j] = (val < thres ? 0 : 255);
}
}
}
#endif
void GrayThresholding(imatrix *image, double thres)
{
int i, j;
double val;
int image_x = imatrix_getRow(image);
int image_y = imatrix_getCol(image);
for (i = 0; i < image_x; i++) {
for (j = 0; j < image_y; j++) {
val = image->p[i][j] / 255.0;
image->p[i][j] = (val < thres ? round(val * 255.0) : 255);
}
}
}