38#include <gsl/gsl_math.h>
39#include <gsl/gsl_vector.h>
40#include <gsl/gsl_linalg.h>
57vector<Vec3f> BoxingTools::colors = vector<Vec3f>();
60#define SVD_CLASSIFIER_DEBUG 0
63#if SVD_CLASSIFIER_DEBUG
64 void printMatrix(
const gsl_matrix *
const A,
const unsigned int rows,
const unsigned int cols,
const string& title =
"" )
66 cout <<
"Printing matrix " << title << endl;
67 cout <<
"It has " << rows <<
" rows and " << cols <<
" columns " << endl;
68 for(
unsigned int i = 0; i < rows; ++i )
70 for(
unsigned int j = 0; j < cols; ++j )
72 cout << gsl_matrix_get(A,i,j) <<
" ";
79void printVector(
const gsl_vector *
const A,
const unsigned int length,
const string& title =
"" )
81 cout <<
"Printing vector " << title << endl;
82 for(
unsigned int i = 0; i <
length; ++i )
84 cout << gsl_vector_get(A,i) <<
" ";
89void print_map(
const map<unsigned int, unsigned int>& mapping )
91 for(map<unsigned int, unsigned int>::const_iterator it = mapping.begin(); it != mapping.end(); ++it)
93 cout << it->first <<
" " << it->second << endl;
98BoxSVDClassifier::BoxSVDClassifier(
const vector<vector<float> >& data,
const unsigned int& classes) :
99 mData(data), mClasses(classes)
113 vector<vector<float> >::const_iterator it = data.begin();
116 for( ; it != data.end(); ++it )
118 if ( it->size() !=
mRows )
120 cerr <<
"ERROR: can not initial the BoxSVDClassifier with vectors of un-equal lengths " << endl;
121 cerr <<
"The vector lengths that did not agree were " <<
mRows <<
" and " << it->size() << endl;
136 unsigned int local_columns =
mColumns;
142 local_columns =
mRows;
145 gsl_matrix * U = gsl_matrix_calloc(
mRows, local_columns );
147 for (
unsigned int i = 0; i <
mRows; ++i )
149 for (
unsigned int j = 0; j <
mColumns; ++j )
151 gsl_matrix_set( A, i, j,
mData[j][i] );
152 if ( j < local_columns )
153 gsl_matrix_set( U, i, j,
mData[j][i] );
156#if SVD_CLASSIFIER_DEBUG
160 gsl_matrix *
V = gsl_matrix_calloc( local_columns, local_columns );
161 gsl_vector * S = gsl_vector_calloc( local_columns );
162 gsl_vector * work = gsl_vector_calloc( local_columns );
164 if ( gsl_linalg_SV_decomp (U,
V, S, work) )
166 cerr <<
"ERROR: gsl returned a non zero value on application of the SVD" << endl;
169#if SVD_CLASSIFIER_DEBUG
170 printMatrix( U,
mRows, local_columns,
"U" );
171 printVector( S, local_columns,
"S" );
172 printMatrix(
V, local_columns, local_columns,
"V");
176 for (
unsigned int j = 0; j <
mColumns; ++j )
179 for (
unsigned int i = 0; i <
mRows; ++i )
181 norm += (float)(gsl_matrix_get( A, i, j)*gsl_matrix_get( A, i, j));
184 for (
unsigned int i = 0; i <
mRows; ++i )
186 gsl_matrix_set( A, i, j, gsl_matrix_get(A,i,j)/norm);
190#if SVD_CLASSIFIER_DEBUG
191 for (
unsigned int j = 0; j <
mColumns; ++j )
194 for (
unsigned int i = 0; i <
mRows; ++i )
196 norm += gsl_matrix_get( A, i, j)*gsl_matrix_get( A, i, j);
198 cout <<
"For column " << j <<
" the squared norm is " << norm << endl;
205 for (
unsigned int i = 0; i <
mColumns; ++i )
207 for (
unsigned int j = 0; j < local_columns; ++j )
210 for (
unsigned int k = 0; k <
mRows; ++k )
212 result += gsl_matrix_get(A,k,i)*gsl_matrix_get(U,k,j);
214 gsl_matrix_set( svd_coords, i, j, result);
218#if SVD_CLASSIFIER_DEBUG
224 for (
unsigned int i = 0; i < 20; ++ i )
233 gsl_vector_free(work);
234 gsl_matrix_free(svd_coords);
245 for(
unsigned int i = 0; i <
mClasses; ++i)
247 unsigned int tally = 0;
248 for (map< unsigned int, unsigned int>::const_iterator it = current_grouping.begin(); it != current_grouping.end(); ++it )
250 if ( it->second == i )
252 for(
unsigned int j = 0; j <
mColumns; ++j )
254 gsl_matrix_set(ref_coords, i, j, gsl_matrix_get( svd_coords, it->first, j ) + gsl_matrix_get( ref_coords, i, j));
262 for(
unsigned int j = 0; j <
mColumns; ++j )
264 gsl_matrix_set(ref_coords, i, j, gsl_matrix_get( ref_coords, i, j )/((
float) tally));
268 vector<vector<float> > distances =
getDistances(svd_coords, ref_coords);
270#if SVD_CLASSIFIER_DEBUG
271 cout <<
"The distance matrix is " << endl;
272 for(
unsigned int i = 0; i < distances.size(); ++i )
274 for(
unsigned int j = 0; j < distances[i].size(); ++j )
276 cout << distances[i][j] <<
" ";
285 map< unsigned int, unsigned int> return_map =
getMapping(distances);
287#if SVD_CLASSIFIER_DEBUG
288 cout <<
"Printing classification map" << endl;
289 print_map(return_map);
292 gsl_matrix_free(ref_coords);
301 srand(
static_cast<unsigned int>(time(0)));
303 vector<unsigned int> random_seed_indices;
304 while ( random_seed_indices.size() <
mClasses )
306 unsigned int random_idx =
static_cast<int>(((float)rand()/RAND_MAX)*matrix_dims);
307 if ( find( random_seed_indices.begin(), random_seed_indices.end(), random_idx ) == random_seed_indices.end() )
309 random_seed_indices.push_back( random_idx );
317 for(
unsigned int i = 0; i < random_seed_indices.size(); ++i)
319 for(
unsigned int j = 0; j < matrix_dims; ++j )
321 gsl_matrix_set(ref_coords, i, j, gsl_matrix_get( svd_coords, random_seed_indices[i], j ));
325#if SVD_CLASSIFIER_DEBUG
326 printMatrix( ref_coords,
mClasses, matrix_dims,
"Reference matrix in first grouping");
332 vector<vector<float> > distances =
getDistances(svd_coords, ref_coords);
334#if SVD_CLASSIFIER_DEBUG
335 cout <<
"The distance matrix is " << endl;
336 for(
unsigned int i = 0; i < distances.size(); ++i )
338 for(
unsigned int j = 0; j < distances[i].size(); ++j )
340 cout << distances[i][j] <<
" ";
349 map< unsigned int, unsigned int> return_map =
getMapping(distances);
351#if SVD_CLASSIFIER_DEBUG
352 cout <<
"Printing classification map, randomly seeded" << endl;
353 print_map(return_map);
356 gsl_matrix_free(ref_coords);
367 vector<vector<float> > distances;
368 for (
unsigned int i = 0; i <
mColumns; ++i )
370 vector<float> ith_distances;
371 for(
unsigned int random_seed_idx = 0; random_seed_idx <
mClasses; ++random_seed_idx )
374 for (
unsigned int j = 0; j <
mColumns; ++j )
376 float value = (float)( (gsl_matrix_get( ref_coords, random_seed_idx, j) - gsl_matrix_get( svd_coords, i, j)) );
377 distance += value * value;
379 ith_distances.push_back(distance);
381 distances.push_back(ith_distances);
391 map< unsigned int, unsigned int> return_map;
392 unsigned int vector_idx = 0;
393 for( vector<vector<float> >::const_iterator it = distances.begin(); it != distances.end(); ++it, ++vector_idx )
395 vector<float>::const_iterator mIt = it->begin();
397 unsigned int min_idx = 0;
398 for (
unsigned int current_idx = 0; mIt != it->end(); ++mIt, ++current_idx )
403 min_idx = current_idx;
406 return_map[vector_idx] = min_idx;
415 vector<unsigned int> current_mappings;
417 for (map< unsigned int, unsigned int>::const_iterator it = grouping.begin(); it != grouping.end(); ++it )
419 if ( find( current_mappings.begin(), current_mappings.end(), it->second ) == current_mappings.end() )
421 current_mappings.push_back( it->second );
425 if ( current_mappings.size() < 2 )
427 cerr <<
"Error, cannot call colMappingByClassSize when less than 2 classes have been specified, I think you created " << current_mappings.size() <<
" classes " << endl;
432 map<unsigned int, unsigned int> mappings_tally;
433 for( vector<unsigned int>::const_iterator it = current_mappings.begin(); it != current_mappings.end(); ++it )
436 mappings_tally[*it] = 0;
440 for (map< unsigned int, unsigned int>::const_iterator it = grouping.begin(); it != grouping.end(); ++it )
442 mappings_tally[it->second] += 1;
446 unsigned int current_mapping_idx = 0;
447 map< unsigned int, unsigned int> return_map;
448 while ( mappings_tally.size() > 0 )
450#if SVD_CLASSIFIER_DEBUG
451 cout <<
"Printing mappings_tally" << endl;
452 print_map(mappings_tally);
455 map< unsigned int, unsigned int>::iterator it = mappings_tally.begin();
456 map< unsigned int, unsigned int>::iterator track_it = mappings_tally.begin();
457 unsigned int current_max = it->second;
458 unsigned int current_idx = it->first;
460 for (; it != mappings_tally.end(); ++it )
462 if ( it->second > current_max )
464 current_max = it->second;
465 current_idx = it->first;
470#if SVD_CLASSIFIER_DEBUG
471 cout <<
"The mapping is " << current_idx <<
" to " << current_mapping_idx << endl;
473 for (map< unsigned int, unsigned int>::const_iterator group_it = grouping.begin(); group_it != grouping.end(); ++group_it )
475 if ( group_it->second == current_idx )
477 return_map[group_it->first] = current_mapping_idx;
481 mappings_tally.erase( current_idx );
483 current_mapping_idx++;
487#if SVD_CLASSIFIER_DEBUG
488 cout <<
"Printing adjusted classification map" << endl;
489 print_map(return_map);
500 float peakval = image->get_value_at(
x,
y);
502 vector<float> profile(radius,0);
503 int radius_squared = radius*radius;
505 static vector<float> squared_numbers;
506 if ( (
unsigned int)(radius+1) > squared_numbers.size() ) {
507 for(
int i = squared_numbers.size(); i <= radius; ++i) {
508 squared_numbers.push_back((
float)(i*i));
512 vector<unsigned int> tally;
515 for(
int k = -radius; k <= radius; ++k) {
516 for(
int j = -radius; j <= radius; ++j) {
522 if ( xx >= image->get_xsize() || xx < 0 )
continue;
523 if ( yy >= image->get_ysize() || yy < 0 )
continue;
526 if ( xx ==
x && yy ==
y)
continue;
529 int square_length = k*k + j*j;
530 if (square_length > radius_squared )
continue;
536 for(
int i = 1; i < radius; ++i) {
537 if ( square_length >= squared_numbers[i] && square_length <= squared_numbers[i+1] ) {
547 float val = peakval - image->get_value_at(xx,yy);
550 if ( profile[idx] > val || profile[idx] == 0 ) profile[idx] = val;
554 float val = (peakval - image->get_value_at(xx,yy) ) / peakval;
557 if ( profile[idx] > val || profile[idx] == 0 ) profile[idx] = val;
560 profile[idx] += image->get_value_at(xx,yy);
568 for(
unsigned int i = 0; i < profile.size(); ++i) {
570 profile[i] /=
static_cast<float>(tally[i]);
571 profile[i] = (peakval - profile[i] ) / peakval;
581 float peakval = image->get_value_at(
x,
y);
582 int radius_squared = radius*radius;
583 for(
int k = -radius; k <= radius; ++k) {
584 for(
int j = -radius; j <= radius; ++j) {
590 if ( xx >= image->get_xsize() || xx < 0 )
continue;
591 if ( yy >= image->get_ysize() || yy < 0 )
continue;
594 if ( xx ==
x && yy ==
y)
continue;
596 if ((k*k+j*j)>radius_squared)
continue;
598 if ( image->get_value_at(xx,yy) > peakval)
return false;
610 if (mode < 0 || mode > 2 ) {
623 int nx = image->get_xsize();
624 int ny = image->get_ysize();
626 vector<IntPoint> solution;
630 for(
int j = r; j < ny-r;++j) {
631 for(
int k = r; k < nx-r;++k) {
633 if (exclusion->get_value_at(k,j) != 0 )
continue;
635 if (image->get_value_at(k,j) < threshold)
continue;
642 vector<float> p(r,0);
644 if (
hi_brid(image,k,j,r,exclusion,p)) {
646 if (p[cradius] >= profile[cradius]) {
654 for (
int ii = 0; ii <= cradius; ++ii) {
655 if (p[ii] < profile[ii]) {
676 float peakval = image->get_value_at(
x,
y);
678 int radius_squared = radius*radius;
680 static vector<float> squared_numbers;
681 if ( (
unsigned int)(radius+1) > squared_numbers.size() ) {
682 for(
int i = squared_numbers.size(); i <= radius; ++i) {
683 squared_numbers.push_back((
float)(i*i));
687 vector<unsigned int> tally;
690 for(
int k = -radius; k <= radius; ++k) {
691 for(
int j = -radius; j <= radius; ++j) {
697 if ( xx >= image->get_xsize() || xx < 0 )
continue;
698 if ( yy >= image->get_ysize() || yy < 0 )
continue;
701 if ( xx ==
x && yy ==
y)
continue;
704 int square_length = k*k + j*j;
705 if (square_length > radius_squared )
continue;
708 if ( image->get_value_at(xx,yy) > peakval)
return false;
714 for(
int i = 1; i < radius; ++i) {
715 if ( square_length >= squared_numbers[i] && square_length <= squared_numbers[i+1] ) {
725 float val = peakval - image->get_value_at(xx,yy);
728 if ( profile[idx] > val || profile[idx] == 0 ) profile[idx] = val;
732 float val = (peakval - image->get_value_at(xx,yy) ) / peakval;
735 if ( profile[idx] > val || profile[idx] == 0 ) profile[idx] = val;
738 profile[idx] += image->get_value_at(xx,yy);
746 for(
unsigned int i = 0; i < profile.size(); ++i) {
748 profile[i] /=
static_cast<float>(tally[i]);
749 profile[i] = (peakval - profile[i] ) / peakval;
762 int radius_squared = radius*radius;
763 for(
int k = -radius; k <= radius; ++k) {
764 for(
int j = -radius; j <= radius; ++j) {
769 if ((k*k+j*j)>radius_squared)
continue;
771 if ( xx >= exclusion->get_xsize() || xx < 0 )
continue;
772 if ( yy >= exclusion->get_ysize() || yy < 0 )
continue;
774 exclusion->set_value_at(xx,yy,1);
781 float currentmax = map->get_value_at(
x,
y);
785 int radius_squared = radius*radius;
786 for(
int k = -radius; k <= radius; ++k) {
787 for(
int j = -radius; j <= radius; ++j) {
793 if ( xx >= map->get_xsize() || xx < 0 )
continue;
794 if ( yy >= map->get_ysize() || yy < 0 )
continue;
797 int square_length = k*k + j*j;
798 if (square_length > radius_squared )
continue;
800 float val = map->get_value_at(xx,yy);
802 if (val > currentmax) {
817 int inx = image->get_xsize();
818 int iny = image->get_ysize();
819 int mnx = mask->get_xsize();
820 int mny = mask->get_ysize();
822 int startx =
x-mnx/2;
823 int endx =startx + mnx;
826 xoffset = abs(startx);
829 if (endx > inx) endx = inx;
831 int starty =
y-mny/2;
832 int endy =starty + mny;
835 yoffset = abs(starty);
838 if (endy > iny) endy = iny;
841 for (
int j = starty; j < endy; ++j ) {
842 for (
int i = startx; i < endx; ++i) {
843 if (mask->get_value_at(xoffset+i-startx,yoffset+j-starty) != 0 ) {
844 image->set_value_at(i,j,val);
850map<unsigned int, unsigned int>
BoxingTools::classify(
const vector<vector<float> >& data,
const unsigned int& classes)
853 map< unsigned int, unsigned int> mapping = classifier.
go();
864 if (
colors.size() == 0 ) {
874 if ( index >=
colors.size() )
876 while (
colors.size() <= index )
881 unsigned int random_idx = rand() %
colors.size();
882 unsigned int random_idx2 = rand() %
colors.size();
883 while ( random_idx2 == random_idx )
885 random_idx2 = rand() %
colors.size();
891 colors.push_back( result );
const vector< vector< float > > & mData
map< unsigned int, unsigned int > getIterativeCluster(const gsl_matrix *const svd_coords, const map< unsigned int, unsigned int > ¤t_grouping)
map< unsigned int, unsigned int > go()
bool setDims(const vector< vector< float > > &data)
map< unsigned int, unsigned int > randomSeedCluster(const gsl_matrix *const svd_coords, unsigned int matrix_dims)
static map< unsigned int, unsigned int > colorMappingByClassSize(const map< unsigned int, unsigned int > &grouping)
map< unsigned int, unsigned int > getMapping(const vector< vector< float > > &distances)
vector< vector< float > > getDistances(const gsl_matrix *const svd_coords, const gsl_matrix *const ref_coords)
EMData stores an image's data and defines core image processing routines.
IntPoint defines an integer-coordinate point in a 1D/2D/3D space.
#define InvalidValueException(val, desc)
double length(const Vector3 &v)