#include "CenSurE.h"
double gaussian(double sigma, double x)
{
return (1/(sigma*sqrt(2*PI)))*exp(-x*x/(sigma*sigma));
}
vector <SDescriptor> GetFeature(IplImage *original_image)
{
double tt;
//0. Image Load
int i, j;
int x, y;
int width, height;
width = original_image->width;
height = original_image->height;
IplImage *gray = cvCreateImage(cvGetSize(original_image), 8, 1);
IplImage *i_image = cvCreateImage(cvSize(original_image->width +1, original_image->height + 1), IPL_DEPTH_32S, 1);
cvCvtColor(original_image, gray, CV_BGR2GRAY);
cvIntegral(gray, i_image);
//1. DoB filter
int min_n = 1;
int max_n = 7;
int n = min_n;//min_n ~ max_n
double max_value = 0;//가장 큰 DoB값, 나중에 normalize하기위해?
double out_value = 0;//DoB구할 때 바깥
double in_value = 0;//DoB구할 때 안쪽
double I_n = 1;
double O_n = 0;
double DoB = 0;
SDoBInfo **m_DoB_info;
m_DoB_info = (SDoBInfo **)malloc(height*sizeof(SDoBInfo *));
for(i = 0; i < height; i++)
{
m_DoB_info[i] = (SDoBInfo *)malloc(width*sizeof(SDoBInfo));
}
//printf("%f\n", max_value);
for(int n = min_n; n <= max_n; n++)
{
I_n = I_n*(2*n + 1)*(2*n + 1)/((2*n + 3)*(2*n + 3));
O_n = I_n*(2*n + 1)*(2*n + 1)/((4*n + 1)*(4*n + 1));
//printf("%d I = %f O = %f\n", n, I_n, O_n);
for(int y = 2*max_n + 1; y < height - 2*max_n; y++)
{
for(int x = 2*max_n + 1; x < width - 2*max_n; x++)
{
out_value = cvGetReal2D(i_image, y + 2*n, x + 2*n) - cvGetReal2D(i_image, y - 2*n - 1, x + 2*n) - cvGetReal2D(i_image, y + 2*n, x - 2*n - 1) + cvGetReal2D(i_image, y - 2*n - 1, x - 2*n - 1);
in_value = cvGetReal2D(i_image, y + n, x + n) - cvGetReal2D(i_image, y - n - 1, x + n) - cvGetReal2D(i_image, y + n, x - n - 1) + cvGetReal2D(i_image, y - n - 1, x - n - 1);
DoB = O_n*out_value - I_n*in_value;
m_DoB_info[y][x].DoB[n-min_n] = DoB;
if(DoB > max_value)
{
max_value = DoB;
}
}
}
}
tt = (double)cvGetTickCount();
//2. Non Max suppression
double current_value;
int current_n, current_x, current_y;
int max_ok = 1;
vector <SDescriptor> m_descriptors;
SDescriptor descriptor;//임시
int gap = 1;
for(int n = min_n+gap; n <= max_n-gap; n++)
{
for(int y = 2*max_n + 1 + gap; y < height - 2*max_n - gap; y++)
{
for(int x = 2*max_n + 1 + gap; x < width - 2*max_n - gap; x++)
{
DoB = m_DoB_info[y][x].DoB[n-1];
if(DoB > max_value/5.0)
{
max_ok = 1;
for(current_n = n-1; current_n <= n+1; current_n++)
{
for(current_y = y-1; current_y <= y+1; current_y++)
{
for(current_x = x-1; current_x <= x+1; current_x++)
{
current_value = m_DoB_info[current_y][current_x].DoB[current_n-1];
if(current_value > DoB)
{
max_ok = 0;
}
}
}
}
if(max_ok == 1)
{
//printf("%d %d\n", x, y);
cvCircle(original_image, cvPoint(x, y), 3, cvScalar(0, 0, 255),1);
descriptor.x = x;
descriptor.y = y;
m_descriptors.push_back(descriptor);
}
}
}
}
}
tt = (double)cvGetTickCount() - tt;
printf( "basic time = %gms\n", tt/(cvGetTickFrequency()*1000.));
//printf("%d", m_descriptors.size());
double descriptor_dx[24][24];
double descriptor_dy[24][24];
double descriptor_adx[24][24];
double descriptor_ady[24][24];
int region_half_width = 12;
int region_width = 24;
int start_x, end_x;
int start_y, end_y;
double dx;
double dy;
int sub_region_width = 9;
int sub_region_half_width = 4;
int sub_region_x, sub_region_y;
double dist;
double weight;
double sum_dx;
double sum_dy;
double sum_adx;
double sum_ady;
int start_sub_x, end_sub_x;
int start_sub_y, end_sub_y;
int descriptor_index;
double sum_descriptor;
for(i=0; i < m_descriptors.size(); i++)
{
//양쪽 2s씩 padding
if( (m_descriptors[i].x >= 2*max_n + 1 + region_half_width) &&
(m_descriptors[i].x < width - 2*max_n - region_half_width) &&
(m_descriptors[i].y >= 2*max_n + 1 + region_half_width) &&
(m_descriptors[i].y < height - 2*max_n - region_half_width))
{
start_x = m_descriptors[i].x - region_half_width;
end_x = m_descriptors[i].x + region_half_width;
start_y = m_descriptors[i].y - region_half_width;
end_y = m_descriptors[i].y + region_half_width;
for(y = start_y; y < end_y; y++)
{
for(x = start_x; x < end_x; x++)
{
dx = cvGetReal2D(gray, y, x+1) - cvGetReal2D(gray, y, x);
dy = cvGetReal2D(gray, y+1, x) - cvGetReal2D(gray, y, x);
descriptor_dx[y-start_y][x-start_x] = dx;
descriptor_dy[y-start_y][x-start_x] = dy;
descriptor_adx[y-start_y][x-start_x] = fabs(dx);
descriptor_ady[y-start_y][x-start_x] = fabs(dy);
}
}
descriptor_index = 0;
for(sub_region_y = start_y + 5; sub_region_y < end_y; sub_region_y+=5)
{
for(sub_region_x = start_x + 5; sub_region_x < end_x; sub_region_x+=5)
{
start_sub_x = sub_region_x - sub_region_half_width;
end_sub_x = sub_region_x + sub_region_half_width;
start_sub_y = sub_region_y - sub_region_half_width;
end_sub_y = sub_region_y + sub_region_half_width;
sum_dx = 0;
sum_dy = 0;
sum_adx = 0;
sum_ady = 0;
for(y = start_sub_y; y <= end_sub_y; y++)
{
for(x = start_sub_x; x <= start_sub_x; x++)
{
dist = sqrt( (double)((x-sub_region_x)*(x-sub_region_x) + (y-sub_region_y)*(y-sub_region_y)));
weight = gaussian(2.5, dist);
//weight = 1;
sum_dx += weight*descriptor_dx[y-start_sub_y][x-start_sub_x];
sum_dy += weight*descriptor_dy[y-start_sub_y][x-start_sub_x];
sum_adx += weight*descriptor_adx[y-start_sub_y][x-start_sub_x];
sum_ady += weight*descriptor_ady[y-start_sub_y][x-start_sub_x];
}
}
dist = sqrt( (double)((sub_region_x - m_descriptors[i].x)*(sub_region_x - m_descriptors[i].x) + (sub_region_y - m_descriptors[i].y)*(sub_region_y - m_descriptors[i].y)));
weight = gaussian(1.3, dist);
//weight = 1;
m_descriptors[i].v[descriptor_index] = weight*sum_dx;
m_descriptors[i].v[descriptor_index+1] = weight*sum_dy;
m_descriptors[i].v[descriptor_index+2] = weight*sum_ady;
m_descriptors[i].v[descriptor_index+3] = weight*sum_ady;
descriptor_index += 4;
}
}
sum_descriptor = 0;
for(j=0; j<64;j++)
{
sum_descriptor += fabs(m_descriptors[i].v[j]);
}
for(j=0; j<64;j++)
{
m_descriptors[i].v[j] = m_descriptors[i].v[j]/sum_descriptor;
}
}
}
for(i = 0; i < height; i++)
{
free(m_DoB_info[i]);
}
free(m_DoB_info);
cvReleaseImage(&gray);
cvReleaseImage(&i_image);
//vector <SDescriptor> m_descriptors;
return m_descriptors;
}