00001
00002
00003 #include <cv.h>
00004 #include <highgui.h>
00005 #include "outlet_pose_estimation/detail/generalized_hough.h"
00006 #include "outlet_pose_estimation/detail/features.h"
00007
00008
00009 using namespace std;
00010
00011 CV_IMPL CvSparseMat*
00012 cvCreateOutletSparseMat( int dims, const int* sizes, int type )
00013 {
00014 type = CV_MAT_TYPE( type );
00015 int pix_size1 = CV_ELEM_SIZE1(type);
00016 int pix_size = pix_size1*CV_MAT_CN(type);
00017 int i, size;
00018 CvMemStorage* storage;
00019
00020 if( pix_size == 0 )
00021 CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
00022
00023 if( dims <= 0 || dims > CV_MAX_DIM_HEAP )
00024 CV_Error( CV_StsOutOfRange, "bad number of dimensions" );
00025
00026 if( !sizes )
00027 CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
00028
00029 for( i = 0; i < dims; i++ )
00030 {
00031 if( sizes[i] <= 0 )
00032 CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
00033 }
00034
00035 CvSparseMat* arr = (CvSparseMat*)cvAlloc(sizeof(*arr)+MAX(0,dims-CV_MAX_DIM)*sizeof(arr->size[0]));
00036
00037 arr->type = CV_SPARSE_MAT_MAGIC_VAL | type;
00038 arr->dims = dims;
00039 arr->refcount = 0;
00040 arr->hdr_refcount = 1;
00041 memcpy( arr->size, sizes, dims*sizeof(sizes[0]));
00042
00043 arr->valoffset = (int)cvAlign(sizeof(CvSparseNode), pix_size1);
00044 arr->idxoffset = (int)cvAlign(arr->valoffset + pix_size, sizeof(int));
00045 size = (int)cvAlign(arr->idxoffset + dims*sizeof(int), sizeof(CvSetElem));
00046
00047
00048 storage = cvCreateMemStorage( 10000000 );
00049
00050 arr->heap = cvCreateSet( 0, sizeof(CvSet), size, storage );
00051
00052 arr->hashsize = CV_SPARSE_HASH_SIZE0;
00053 size = arr->hashsize*sizeof(arr->hashtable[0]);
00054
00055 arr->hashtable = (void**)cvAlloc( size );
00056 memset( arr->hashtable, 0, size );
00057
00058 return arr;
00059 }
00060
00061
00062
00063 void filterOutletOutliers(vector<feature_t>& features, vector<feature_t>& dst_outlet, int accuracy)
00064 {
00065
00066
00067 bool first = 0;
00068 bool second = 0;
00069 bool third = 0;
00070 bool forth = 0;
00071 if ((int)dst_outlet.size()/3 < 3)
00072 {
00073 third = 1;
00074 forth = 1;
00075 }
00076
00077 int nOutlets = (int)dst_outlet.size()/3;
00078 for (int i=0;i<(int)dst_outlet.size();i++)
00079 {
00080 float distance = -1;
00081 float min_distance = (float)1e38;
00082 for (int j=0;j<(int)features.size();j++)
00083 {
00084 if (dst_outlet[i].class_id == features[j].class_id)
00085 {
00086 distance = (features[j].pt.x - dst_outlet[i].pt.x)*(features[j].pt.x - dst_outlet[i].pt.x)+
00087 (features[j].pt.y - dst_outlet[i].pt.y)*(features[j].pt.y - dst_outlet[i].pt.y);
00088 if (distance < min_distance)
00089 min_distance = distance;
00090 }
00091 }
00092
00093 distance = min_distance;
00094
00095 if ((distance < 1e38)&&(distance < accuracy*accuracy))
00096 {
00097 if (nOutlets == 4)
00098 {
00099 if ((i==0)||(i==1)||(i==8))
00100 {
00101 first = 1;
00102 }
00103 if ((i==2)||(i==3)||(i==9))
00104 {
00105 second = 1;
00106 }
00107 if ((i==4)||(i==5)||(i==10))
00108 {
00109 third = 1;
00110 }
00111 if ((i==6)||(i==7)||(i==11))
00112 {
00113 forth = 1;
00114 }
00115 }
00116 if (nOutlets == 2)
00117 {
00118 if ((i==0)||(i==1)||(i==4))
00119 {
00120 first = 1;
00121 }
00122 if ((i==2)||(i==3)||(i==5))
00123 {
00124 second = 1;
00125 }
00126
00127 }
00128
00129 }
00130
00131 }
00132 if (!(first && second && third && forth))
00133 {
00134 dst_outlet.clear();
00135 return;
00136 }
00137
00138
00139
00140
00141
00142 else
00143 {
00144 float alpha = (float)CV_PI;
00145 float beta = (float)CV_PI;
00146 float gamma = (float)CV_PI;
00147 float a,b,c;
00148
00149 int overSize = (int)dst_outlet.size()%3;
00150 for (int i=0;i<nOutlets;i++)
00151 {
00152 a = (dst_outlet[2*i].pt.x - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.x)*(dst_outlet[2*i].pt.x - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.x)+
00153 (dst_outlet[2*i].pt.y - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.y)*(dst_outlet[2*i].pt.y - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.y);
00154 b = (dst_outlet[2*i+1].pt.x - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.x)*(dst_outlet[2*i+1].pt.x - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.x)+
00155 (dst_outlet[2*i+1].pt.y - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.y)*(dst_outlet[2*i+1].pt.y - dst_outlet[(int)dst_outlet.size() - overSize - nOutlets+i].pt.y);
00156 c = (dst_outlet[2*i].pt.x - dst_outlet[2*i+1].pt.x)*(dst_outlet[2*i].pt.x - dst_outlet[2*i+1].pt.x)+
00157 (dst_outlet[2*i].pt.y - dst_outlet[2*i+1].pt.y)*(dst_outlet[2*i].pt.y - dst_outlet[2*i+1].pt.y);
00158
00159 if ((a > 0)&&( b> 0))
00160 alpha = acos((a + b - c)/2/sqrt(a*b));
00161 if ((a > 0)&&( b> 0))
00162 beta = acos((a + c - b)/2/sqrt(a*c));
00163 gamma = (float)CV_PI - alpha - beta;
00164
00165
00166 if ((alpha > CV_PI/2)||(beta > CV_PI/2)||(gamma > CV_PI/2))
00167 {
00168 dst_outlet.clear();
00169 return;
00170 }
00171 }
00172
00173 }
00174
00175
00176
00177 #if 1
00178 CvPoint min, max;
00179 float coeff = 2.0f;
00180 min.x = (int)dst_outlet[0].pt.x;
00181 min.y = (int)dst_outlet[0].pt.y;
00182 max.x = min.x;
00183 max.y = min.y;
00184 for (int i=1; i<(int)dst_outlet.size(); i++)
00185 {
00186 if ((int)dst_outlet[i].pt.x > max.x)
00187 max.x = (int)dst_outlet[i].pt.x ;
00188 if ((int)dst_outlet[i].pt.y > max.y)
00189 max.y = (int)dst_outlet[i].pt.y ;
00190 if ((int)dst_outlet[i].pt.x < min.x)
00191 min.x = (int)dst_outlet[i].pt.x ;
00192 if ((int)dst_outlet[i].pt.y < min.y)
00193 min.y = (int)dst_outlet[i].pt.y ;
00194 }
00195 int width = max.x - min.x;
00196 int height = max.y - min.y;
00197 min.x -=(int)(width*0.2);
00198 max.x +=(int)(width*0.2);
00199 min.y -=(int)(height*0.2);
00200 max.y +=(int)(height*0.2);
00201
00202 int count = 0;
00203 for (int i=0;i<(int)features.size(); i++)
00204 {
00205 if (((int)features[i].pt.x >= min.x)&&((int)features[i].pt.y >= min.y)&&
00206 ((int)features[i].pt.x <= max.x)&&((int)features[i].pt.y <= max.y))
00207 {
00208 count++;
00209 }
00210
00211 }
00212
00213 if (count > (int)(coeff*dst_outlet.size()))
00214 {
00215 dst_outlet.clear();
00216 return;
00217 }
00218 #endif
00219
00220
00221
00222
00223 }
00224
00225 CvPoint* getOutletCenter(feature_t feature, const vector<feature_t>& train_features, int feature_id, float angle1, float x_scale, float y_scale, float angle2)
00226 {
00227 CvPoint* result;
00228 int train_length = (int)train_features.size();
00229 if ((feature_id < 0)||(feature_id > (train_length-1)))
00230 return NULL;
00231 CvPoint outlet_center;
00232 outlet_center.x = 0;
00233 outlet_center.y = 0;
00234 for (int i=0;i<train_length;i++)
00235 {
00236 outlet_center.x += (int)train_features[i].pt.x;
00237 outlet_center.y += (int)train_features[i].pt.y;
00238 }
00239 outlet_center.x /= train_length;
00240 outlet_center.y /= train_length;
00241
00242 float rel_center_x = - outlet_center.x + train_features[feature_id].pt.x;
00243 float rel_center_y = - outlet_center.y + train_features[feature_id].pt.y;
00244 float t1 = rel_center_x * cos(angle1) + rel_center_y*sin(angle1);
00245 float t2 = - rel_center_x * sin(angle1) + rel_center_y * cos(angle1);
00246 rel_center_x = t1*x_scale;
00247 rel_center_y = t2*y_scale;
00248 t1 = rel_center_x * cos(angle2) + rel_center_y*sin(angle2);
00249 t2 = - rel_center_x * sin(angle2) + rel_center_y * cos(angle2);
00250
00251 result = new CvPoint();
00252 result->x = (int)(feature.pt.x-t1);
00253 result->y = (int)(feature.pt.y-t2);
00254
00255 return result;
00256
00257 }
00258
00259 CvSparseMat* buildHoughHist(vector<feature_t>& input, const vector<feature_t>& train_features, int* hist_size, float** ranges)
00260 {
00261 CvSparseMat* hist;
00262
00263 hist = cvCreateOutletSparseMat(6,hist_size,CV_32FC1);
00264
00265 int* hist_size2 = new int[7];
00266 for (int i=0;i<6;i++)
00267 hist_size2[i] = hist_size[i];
00268 hist_size2[6] = (int)train_features.size();
00269
00270 CvSparseMat* feature_votes = cvCreateOutletSparseMat(7,hist_size2,CV_8UC1);
00271
00272
00273 int* idx = new int[6];
00274 int* votes_idx = new int[7];
00275
00276
00277 float blur_coeff = 0.17f;
00278
00279 for (int n = 0; n < (int)input.size();n++)
00280 {
00281 for (int feature_id = 0; feature_id < (int)train_features.size(); feature_id++)
00282 {
00283 if (input[n].class_id != train_features[feature_id].class_id)
00284 continue;
00285
00286 for (float angle1 = ranges[2][0]+(ranges[2][1]-ranges[2][0])/(hist_size[2]*2); angle1 <= ranges[2][1]; angle1 += ((ranges[2][1]-ranges[2][0] > 0) ? (ranges[2][1]-ranges[2][0])/hist_size[2] : 1))
00287 {
00288 for (float x_scale = ranges[3][0]+(ranges[3][1]-ranges[3][0])/(hist_size[3]*2); x_scale <= ranges[3][1]; x_scale += ((ranges[3][1]-ranges[3][0] > 0) ? (ranges[3][1]-ranges[3][0])/hist_size[3] : 1))
00289 {
00290 for (float y_scale = ranges[4][0]+(ranges[4][1]-ranges[4][0])/(hist_size[4]*2); y_scale <= ranges[4][1]; y_scale += ((ranges[4][1]-ranges[4][0] > 0) ? (ranges[4][1]-ranges[4][0])/hist_size[4] : 1))
00291 {
00292 for (float angle2 = ranges[5][0]+(ranges[5][1]-ranges[5][0])/(hist_size[5]*2); angle2 <= ranges[5][1]; angle2 += ((ranges[5][1]-ranges[5][0] > 0) ? (ranges[5][1]-ranges[5][0])/hist_size[5] : 1))
00293 {
00294
00295 if(abs(input[n].pt.x - 379) < 5 && abs(input[n].pt.y - 312) < 5 &&
00296 fabs(fabs(angle1)) < 0.2 && fabs(fabs(angle2) - 3.1415/3) < 0.2)
00297 {
00298 int w = 1;
00299 }
00300
00301 CvPoint* center = getOutletCenter(input[n],train_features,feature_id,angle1,x_scale,y_scale,angle2);
00302
00303 if (center && (center->x >= ranges[0][0]) && (center->x < ranges[0][1]) && (center->y >= ranges[1][0]) && (center->y < ranges[1][1]))
00304 {
00305
00306 float idx0 = ((center->x - ranges[0][0])/(ranges[0][1]-ranges[0][0]) * hist_size[0]);
00307 float idx1 = ((center->y - ranges[1][0])/(ranges[1][1]-ranges[1][0]) * hist_size[1]);
00308 idx[0] = (int)idx0;
00309 idx[1] = (int)idx1;
00310 idx[2] = (ranges[2][1] != ranges[2][0]) ? (int)((angle1 - ranges[2][0])/(ranges[2][1]-ranges[2][0]) * hist_size[2]) : 0;
00311 idx[3] = (ranges[3][1] != ranges[3][0]) ?(int)((x_scale - ranges[3][0])/(ranges[3][1]-ranges[3][0]) * hist_size[3]) : 0;
00312 idx[4] = (ranges[4][1] != ranges[4][0]) ?(int)((y_scale - ranges[4][0])/(ranges[4][1]-ranges[4][0]) * hist_size[4]) : 0;
00313 idx[5] = (ranges[5][1] != ranges[5][0]) ?(int)((angle2 - ranges[5][0])/(ranges[5][1]-ranges[5][0]) * hist_size[5]) : 0;
00314
00315
00316 bool isOK = true;
00317 for (int i=0;i<2; i++)
00318 {
00319 if (idx[i] >= hist_size[i])
00320 {
00321 idx[i] = hist_size[i]-1;
00322 isOK = false;
00323 }
00324 if (idx[i] < 0)
00325 {
00326 idx[i] = 0;
00327 isOK = false;
00328 }
00329 }
00330
00331 if (isOK)
00332 {
00333 for (int i=0;i<6;i++)
00334 votes_idx[i] = idx[i];
00335 votes_idx[6] = feature_id;
00336
00337 int val = (int)cvGetND(feature_votes,votes_idx).val[0];
00338
00339 if (val)
00340 {
00341 isOK = false;
00342 }
00343 else
00344 {
00345 cvSetND(feature_votes,votes_idx,cvScalar(1));
00346 }
00347 }
00348
00349 if (isOK)
00350 {
00351
00352 float value = (float)cvGetRealND(hist,idx);
00353 cvSetRealND(hist,idx,++value);
00354
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 }
00408
00409
00410 delete center;
00411 center = 0;
00412 }
00413 if (center)
00414 delete center;
00415 }
00416 }
00417 }
00418 }
00419 }
00420 }
00421 delete[] idx;
00422 delete[] votes_idx;
00423 cvReleaseSparseMat(&feature_votes);
00424
00425 return hist;
00426 }
00427
00428
00429 float** getMaxHistValues(const CvHistogram* hist, int* hist_size)
00430 {
00431 float** values = new float*[1];
00432 *values = new float[6];
00433
00434 float max_val, min_val;
00435 int* idx = new int[6];
00436 cvGetMinMaxHistValue(hist,&min_val,&max_val,0,idx);
00437 printf("\nVotes: %f\n ",max_val);
00438
00439 (*values)[0] = hist->thresh[0][0]+(hist->thresh[0][1]-hist->thresh[0][0])/hist_size[0]*idx[0];
00440 (*values)[1] = hist->thresh[1][0]+(hist->thresh[1][1]-hist->thresh[1][0])/hist_size[1]*idx[1];
00441 (*values)[2] = hist->thresh[2][0]+(hist->thresh[2][1]-hist->thresh[2][0])/hist_size[2]*idx[2];
00442 (*values)[3] = hist->thresh[3][0]+(hist->thresh[3][1]-hist->thresh[3][0])/hist_size[3]*idx[3];
00443 (*values)[4] = hist->thresh[4][0]+(hist->thresh[4][1]-hist->thresh[4][0])/hist_size[4]*idx[4];
00444 (*values)[5] = hist->thresh[5][0]+(hist->thresh[5][1]-hist->thresh[5][0])/hist_size[5]*idx[5];
00445
00446 delete[] idx;
00447 return values;
00448 }
00449
00450
00451
00452 void getMaxHistValues(const CvSparseMat* hist, int* hist_size, float** ranges, float** &maxs, int& count, int MIN_VOTES)
00453 {
00454 count = 0;
00455
00456 CvSparseMatIterator mat_iterator;
00457 CvSparseNode* node = cvInitSparseMatIterator( hist, &mat_iterator );
00458
00459 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
00460 {
00461
00462 float val = *(float*)CV_NODE_VAL( hist, node );
00463
00464 if (val >= MIN_VOTES)
00465 (count) ++;
00466 }
00467
00468
00469 if (count > 0)
00470 {
00471 maxs = new float*[count];
00472 for (int i=0; i<(count); i++)
00473 maxs[i] = new float[6];
00474
00475 int i=0;
00476 node = cvInitSparseMatIterator( hist, &mat_iterator );
00477 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
00478 {
00479 int* idx = CV_NODE_IDX( hist, node );
00480 float val = *(float*)CV_NODE_VAL( (CvSparseMat*)hist, node );
00481
00482 if (val >= MIN_VOTES)
00483 {
00484 maxs[i][0] = (float)(ranges[0][0]+(ranges[0][1]-ranges[0][0])/hist_size[0]*(idx[0]+0.5));
00485 maxs[i][1] = (float)(ranges[1][0]+(ranges[1][1]-ranges[1][0])/hist_size[1]*(idx[1]+0.5));
00486 maxs[i][2] = (float)(ranges[2][0]+(ranges[2][1]-ranges[2][0])/hist_size[2]*(idx[2]+0.5));
00487 maxs[i][3] = (float)(ranges[3][0]+(ranges[3][1]-ranges[3][0])/hist_size[3]*(idx[3]+0.5));
00488 maxs[i][4] = (float)(ranges[4][0]+(ranges[4][1]-ranges[4][0])/hist_size[4]*(idx[4]+0.5));
00489 maxs[i][5] = (float)(ranges[5][0]+(ranges[5][1]-ranges[5][0])/hist_size[5]*(idx[5]+0.5));
00490 i++;
00491 }
00492
00493
00494 }
00495
00496 }
00497 else
00498 {
00499 maxs = NULL;
00500 count = 0;
00501 }
00502
00503 }
00504
00505 int getMaxHistValues(const CvSparseMat* hist, int* hist_size, float** ranges, float** &maxs, int& count)
00506 {
00507
00508 count = 0;
00509 float MIN_VOTES = 0;
00510 CvSparseMatIterator mat_iterator;
00511 CvSparseNode* node = cvInitSparseMatIterator( hist, &mat_iterator );
00512
00513 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
00514 {
00515
00516 float val = *(float*)CV_NODE_VAL( hist, node );
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 if (val > MIN_VOTES)
00548 MIN_VOTES = val-1;
00549 }
00550
00551
00552 node = cvInitSparseMatIterator( hist, &mat_iterator );
00553
00554 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
00555 {
00556
00557 float val = *(float*)CV_NODE_VAL( hist, node );
00558
00559 if (val >= MIN_VOTES)
00560 (count) ++;
00561 }
00562
00563
00564 if (count > 0)
00565 {
00566 maxs = new float*[count];
00567 for (int i=0; i<(count); i++)
00568 maxs[i] = new float[6];
00569
00570 int i=0;
00571 node = cvInitSparseMatIterator( hist, &mat_iterator );
00572 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
00573 {
00574 int* idx = CV_NODE_IDX( hist, node );
00575 float val = *(float*)CV_NODE_VAL( hist, node );
00576
00577 if (val >= MIN_VOTES)
00578 {
00579 maxs[i][0] = (float)(ranges[0][0]+(ranges[0][1]-ranges[0][0])/hist_size[0]*(idx[0]+0.5));
00580 maxs[i][1] = (float)(ranges[1][0]+(ranges[1][1]-ranges[1][0])/hist_size[1]*(idx[1]+0.5));
00581 maxs[i][2] = (float)(ranges[2][0]+(ranges[2][1]-ranges[2][0])/hist_size[2]*(idx[2]+0.5));
00582 maxs[i][3] = (float)(ranges[3][0]+(ranges[3][1]-ranges[3][0])/hist_size[3]*(idx[3]+0.5));
00583 maxs[i][4] = (float)(ranges[4][0]+(ranges[4][1]-ranges[4][0])/hist_size[4]*(idx[4]+0.5));
00584 maxs[i][5] = (float)(ranges[5][0]+(ranges[5][1]-ranges[5][0])/hist_size[5]*(idx[5]+0.5));
00585 i++;
00586 }
00587
00588
00589 }
00590
00591 }
00592 else
00593 {
00594 maxs = NULL;
00595 count = 0;
00596 }
00597
00598 int res = (int)MIN_VOTES;
00599 return res;
00600
00601 }
00602
00603
00604
00605
00606 void calcOutletPosition(const vector<feature_t>& train_features, float* affine_transform, vector<feature_t>& features)
00607 {
00608 CvPoint center = cvPoint((int)(affine_transform[0]),(int)(affine_transform[1]));
00609 float angle1 = affine_transform[2];
00610 float x_scale = affine_transform[3];
00611 float y_scale = affine_transform[4];
00612 float angle2 = affine_transform[5];
00613 int train_length = (int)train_features.size();
00614
00615
00616 CvPoint outlet_center;
00617 outlet_center.x = 0;
00618 outlet_center.y = 0;
00619 for (int i=0;i<train_length;i++)
00620 {
00621 outlet_center.x += (int)train_features[i].pt.x;
00622 outlet_center.y += (int)train_features[i].pt.y;
00623 }
00624 outlet_center.x /= train_length;
00625 outlet_center.y /= train_length;
00626
00627 for (int i=0; i< train_length; i++)
00628 {
00629 float rel_center_x = - outlet_center.x + train_features[i].pt.x;
00630 float rel_center_y = - outlet_center.y + train_features[i].pt.y;
00631 float t1 = rel_center_x * cos(angle1) + rel_center_y*sin(angle1);
00632 float t2 = - rel_center_x * sin(angle1) + rel_center_y * cos(angle1);
00633 rel_center_x = t1*x_scale;
00634 rel_center_y = t2*y_scale;
00635 t1 = rel_center_x * cos(angle2) + rel_center_y*sin(angle2);
00636 t2 = - rel_center_x * sin(angle2) + rel_center_y * cos(angle2);
00637
00638 CvPoint result_point;
00639 result_point.x = (int)(center.x+t1);
00640 result_point.y = (int)(center.y+t2);
00641 feature_t feature;
00642 feature.size = train_features[i].size;
00643 feature.pt = result_point;
00644 feature.class_id = train_features[i].class_id;
00645
00646 features.push_back(feature);
00647 }
00648
00649
00650 }
00651
00652
00653
00654
00655
00656 void filterFalseMovements(const vector<feature_t>& projected_outlet, vector<feature_t>& dst_outlet)
00657 {
00658
00659 vector <float> orig_right;
00660 vector <float> orig_left;
00661 vector <float> new_right;
00662 vector <float> new_left;
00663 float dist = 0.0f;
00664 float diff_coeff = 1.6f;
00665 float diff_coeff_1 = 1/diff_coeff;
00666 int nPower = (int)dst_outlet.size()/3*2;
00667 int nGround = nPower/2;
00668 orig_right.resize(nPower+nGround);
00669 orig_left.resize(nPower+nGround);
00670 new_right.resize(nPower+nGround);
00671 new_left.resize(nPower+nGround);
00672 for (int i=0;i<nGround;i++)
00673 {
00674 dist = (dst_outlet[nPower+i].pt.x-dst_outlet[2*i].pt.x)*(dst_outlet[nPower+i].pt.x-dst_outlet[2*i].pt.x)+
00675 (dst_outlet[nPower+i].pt.y-dst_outlet[2*i].pt.y)*(dst_outlet[nPower+i].pt.y-dst_outlet[2*i].pt.y);
00676 new_right[nPower+i] = dist;
00677 new_left[2*i] = dist;
00678
00679 dist = (dst_outlet[nPower+i].pt.x-dst_outlet[2*i+1].pt.x)*(dst_outlet[nPower+i].pt.x-dst_outlet[2*i+1].pt.x)+
00680 (dst_outlet[nPower+i].pt.y-dst_outlet[2*i+1].pt.y)*(dst_outlet[nPower+i].pt.y-dst_outlet[2*i+1].pt.y);
00681 new_left[nPower+i] = dist;
00682 new_right[2*i+1] = dist;
00683
00684 dist = (dst_outlet[2*i+1].pt.x-dst_outlet[2*i].pt.x)*(dst_outlet[2*i+1].pt.x-dst_outlet[2*i].pt.x)+
00685 (dst_outlet[2*i+1].pt.y-dst_outlet[2*i].pt.y)*(dst_outlet[2*i+1].pt.y-dst_outlet[2*i].pt.y);
00686 new_right[2*i] = dist;
00687 new_left[2*i+1] = dist;
00688
00689 dist = (projected_outlet[nPower+i].pt.x-projected_outlet[2*i].pt.x)*(projected_outlet[nPower+i].pt.x-projected_outlet[2*i].pt.x)+
00690 (projected_outlet[nPower+i].pt.y-projected_outlet[2*i].pt.y)*(projected_outlet[nPower+i].pt.y-projected_outlet[2*i].pt.y);
00691 orig_right[nPower+i] = dist;
00692 orig_left[2*i] = dist;
00693
00694 dist = (projected_outlet[nPower+i].pt.x-projected_outlet[2*i+1].pt.x)*(projected_outlet[nPower+i].pt.x-projected_outlet[2*i+1].pt.x)+
00695 (projected_outlet[nPower+i].pt.y-projected_outlet[2*i+1].pt.y)*(projected_outlet[nPower+i].pt.y-projected_outlet[2*i+1].pt.y);
00696 orig_left[nPower+i] = dist;
00697 orig_right[2*i+1] = dist;
00698
00699 dist = (projected_outlet[2*i+1].pt.x-projected_outlet[2*i].pt.x)*(projected_outlet[2*i+1].pt.x-projected_outlet[2*i].pt.x)+
00700 (projected_outlet[2*i+1].pt.y-projected_outlet[2*i].pt.y)*(projected_outlet[2*i+1].pt.y-projected_outlet[2*i].pt.y);
00701 orig_right[2*i] = dist;
00702 orig_left[2*i+1] = dist;
00703 }
00704
00705 for (int i=0;i<nPower+nGround;i++)
00706 {
00707 if (new_left[i] > 0)
00708 {
00709 float rel = orig_left[i]/new_left[i];
00710 if ((rel > diff_coeff)||(rel <diff_coeff_1))
00711 {
00712 dst_outlet[i].pt = projected_outlet[i].pt;
00713 continue;
00714
00715 }
00716 }
00717
00718 if (new_right[i] > 0)
00719 {
00720 float rel = orig_right[i]/new_right[i];
00721 if ((rel > diff_coeff)||(rel <diff_coeff_1))
00722 {
00723 dst_outlet[i].pt = projected_outlet[i].pt;
00724 continue;
00725 }
00726 }
00727 }
00728
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 }
00766
00767
00768
00769
00770
00771 void getNearestFeaturesIndexes(const vector<feature_t>& src_outlet, const vector<feature_t>& features, int* indexes, int accuracy, float max_diff_coeff)
00772 {
00773
00774
00775 for (int i=0;i<(int)src_outlet.size();i++)
00776 {
00777 int min_index = -1;
00778 float min_distance = (float)1e30;
00779 float last_min_distance;
00780 for (int j=0;j<(int)features.size();j++)
00781 {
00782 if (features[j].class_id == src_outlet[i].class_id)
00783 {
00784 float distance = (features[j].pt.x - src_outlet[i].pt.x)*(features[j].pt.x - src_outlet[i].pt.x)+
00785 (features[j].pt.y - src_outlet[i].pt.y)*(features[j].pt.y - src_outlet[i].pt.y);
00786 if ((distance < min_distance))
00787 {
00788 last_min_distance = min_distance;
00789 min_distance = distance;
00790 min_index = j;
00791 }
00792 else
00793 {
00794
00795 if ((distance < last_min_distance)&&((features[j].pt.x != features[min_index].pt.x)||(features[j].pt.y != features[min_index].pt.y)))
00796 {
00797 last_min_distance = distance;
00798 }
00799 }
00800 }
00801
00802 }
00803 if (min_distance < accuracy*accuracy)
00804 indexes[i] = min_index;
00805 else
00806 min_index = -1;
00807 if (min_index > -1)
00808 {
00809 if ((min_distance > 0) && (last_min_distance/min_distance <= max_diff_coeff))
00810 {
00811 indexes[i] = -1;
00812
00813 }
00814 }
00815 }
00816
00817 for (int i=0;i< (int)(src_outlet.size());i++)
00818 {
00819 if (indexes[i] >=0)
00820 {
00821 bool wasRepeat = false;
00822 for (int j=i+1;j< (int)(src_outlet.size());j++)
00823 {
00824 if (indexes[i]==indexes[j])
00825 {
00826 indexes[j] = -1;
00827 wasRepeat = true;
00828 }
00829 }
00830 if (wasRepeat)
00831 indexes[i] = -1;
00832 }
00833 }
00834 }
00835
00836
00837
00838
00839
00840
00841 void attractOutletToFeatures(const vector<feature_t>& train_features, const vector<feature_t>& features,vector<feature_t>& dst_outlet, const int* indexes, float max_diff_coeff)
00842 {
00843 for (int i=0;i< (int)(dst_outlet.size());i++)
00844 {
00845
00846
00847 int min_index = -1;
00848 float min_distance = (float)1e38;
00849 float last_min_distance;
00850 for (int j=0;j<(int)features.size();j++)
00851 {
00852 if (features[j].class_id == dst_outlet[i].class_id)
00853 {
00854 float distance = (features[j].pt.x - dst_outlet[i].pt.x)*(features[j].pt.x - dst_outlet[i].pt.x)+
00855 (features[j].pt.y - dst_outlet[i].pt.y)*(features[j].pt.y - dst_outlet[i].pt.y);
00856 if (distance < min_distance)
00857 {
00858 last_min_distance = distance;
00859
00860 float acc = (float)((train_features[1].pt.x - train_features[0].pt.x)*(train_features[1].pt.x - train_features[0].pt.x)+
00861 (train_features[1].pt.y - train_features[0].pt.y)*(train_features[1].pt.y - train_features[0].pt.y))/9;
00862 if (distance < acc)
00863 {
00864 min_distance = distance;
00865 min_index = j;
00866 }
00867 }
00868 else
00869 {
00870 if (distance < last_min_distance)
00871 {
00872 last_min_distance = distance;
00873 }
00874 }
00875 }
00876 }
00877 if (min_index >= 0)
00878 {
00879 if (((min_distance > 0) && (last_min_distance/min_distance <= max_diff_coeff))||(min_distance == 0))
00880 dst_outlet[i] = features[min_index];
00881
00882 }
00883 else
00884
00885
00886
00887 if (indexes[i] >=0)
00888 {
00889 dst_outlet[i] = features[indexes[i]];
00890 }
00891 }
00892 }
00893
00894
00895 void calcExactLocation(vector<feature_t>& features,const vector<feature_t>& train_features, vector<feature_t>& src_outlet,
00896 vector<feature_t>& dst_outlet, float& reprojectionError, int accuracy, bool useSecondAttraction)
00897 {
00898 float max_diff_coeff = 2.0f;
00899 if (((int)train_features.size()) == ((int)src_outlet.size()))
00900 {
00901 vector<CvPoint> train_points;
00902 train_points.clear();
00903
00904
00905 vector<CvPoint> features_points;
00906 features_points.clear();
00907 int* indexes = new int[(int)train_features.size()];
00908
00909
00910 for (int i=0;i<(int)train_features.size();i++)
00911 {
00912 indexes[i] = -1;
00913 }
00914
00915
00916
00917
00918
00919
00920 getNearestFeaturesIndexes(src_outlet,features, indexes, accuracy, max_diff_coeff);
00921
00922
00923 for (int i=0;i< (int)(src_outlet.size());i++)
00924 {
00925 if (indexes[i] >=0)
00926 {
00927 train_points.push_back(train_features[i].pt);
00928 features_points.push_back(features[indexes[i]].pt);
00929 }
00930 }
00931 int nPoints = (int)train_points.size();
00932
00933
00934 if (((int)train_points.size() > 3) )
00935 {
00936
00937 CvMat* homography = cvCreateMat(2, 3, CV_32FC1);
00938 FindAffineTransform(train_points, features_points, homography);
00939 reprojectionError = CalcAffineReprojectionError(train_points, features_points, homography) + 1000000 - 10000*(int)train_points.size();
00940 dst_outlet.clear();
00941 MapFeaturesAffine(train_features, dst_outlet, homography);
00942
00943 vector<feature_t> projected_outlet = dst_outlet;
00944
00945
00946 if (useSecondAttraction)
00947 {
00948 attractOutletToFeatures(train_features,features,dst_outlet,indexes,max_diff_coeff);
00949 }
00950
00951
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 #if 1
00980 filterFalseMovements(projected_outlet, dst_outlet);
00981 #endif
00982
00983 cvReleaseMat(&homography);
00984
00985 }
00986 else
00987 {
00988 dst_outlet.clear();
00989 reprojectionError = (float)1e38;
00990 }
00991
00992
00993 delete[] indexes;
00994 }
00995 else
00996 {
00997 dst_outlet.clear();
00998 reprojectionError = (float)1e38;
00999 }
01000
01001
01002 }
01003
01004
01005 void convertFeaturesToOutlet(const vector<feature_t>& res_features, vector<outlet_t>& holes, IplImage* resImage)
01006 {
01007 holes.clear();
01008 outlet_t outlet;
01009
01010 for (int i=0;i<(int)res_features.size()/3;i++)
01011 {
01012 outlet.hole1 = res_features[2*i].pt;
01013 outlet.hole2 = res_features[2*i+1].pt;
01014 outlet.ground_hole = res_features[(int)res_features.size()/3*2+i].pt;
01015 holes.push_back(outlet);
01016 if (resImage)
01017 {
01018 CvScalar pointColor = cvScalar(255,0,50);
01019 cvLine(resImage, cvPoint((int)(outlet.ground_hole.x+7), (int)(outlet.ground_hole.y)), cvPoint((int)(outlet.ground_hole.x-7),(int)(outlet.ground_hole.y)),pointColor,2);
01020 cvLine(resImage, cvPoint((int)(outlet.ground_hole.x), (int)(outlet.ground_hole.y+7)), cvPoint((int)(outlet.ground_hole.x), (int)(outlet.ground_hole.y-7)),pointColor,2);
01021 pointColor = cvScalar(0,255,50);
01022 cvLine(resImage, cvPoint((int)(outlet.hole1.x+7), (int)(outlet.hole1.y)), cvPoint((int)(outlet.hole1.x-7),(int)(outlet.hole1.y)),pointColor,2);
01023 cvLine(resImage, cvPoint((int)(outlet.hole1.x), (int)(outlet.hole1.y+7)), cvPoint((int)(outlet.hole1.x), (int)(outlet.hole1.y-7)),pointColor,2);
01024 cvLine(resImage, cvPoint((int)(outlet.hole2.x+7), (int)(outlet.hole2.y)), cvPoint((int)(outlet.hole2.x-7),(int)(outlet.hole2.y)),pointColor,2);
01025 cvLine(resImage, cvPoint((int)(outlet.hole2.x), (int)(outlet.hole2.y+7)), cvPoint((int)(outlet.hole2.x), (int)(outlet.hole2.y-7)),pointColor,2);
01026 }
01027 }
01028 }
01029
01030 void convertFeaturesToOutlet(const vector<feature_t>& res_features, const vector<bool>& is_detected, vector<outlet_t>& holes)
01031 {
01032 holes.clear();
01033 outlet_t outlet;
01034
01035 for (int i=0;i<(int)res_features.size()/3;i++)
01036 {
01037 outlet.hole1 = res_features[2*i].pt;
01038 outlet.hole1_detected = is_detected[2*i];
01039
01040 outlet.hole2 = res_features[2*i+1].pt;
01041 outlet.hole2_detected = is_detected[2*i+1];
01042
01043 outlet.ground_hole = res_features[(size_t)res_features.size()/3*2+i].pt;
01044 outlet.ground_hole_detected = is_detected[(size_t)res_features.size()/3*2+i];
01045
01046 holes.push_back(outlet);
01047 }
01048 }
01049
01050
01051
01052
01053 void repaintFeatures(const vector<feature_t> hole_candidates, const vector<feature_t>& hole_features, vector<feature_t>& hole_candidates_repainted, int accuracy = 10)
01054 {
01055 float dist_coeff = (float)0.015;
01056 for(int i = 0; i < (int)hole_candidates.size(); i++)
01057 {
01058 float min_dist = 1e10;
01059 int min_idx = -1;
01060 for (int j=0; j<(int)hole_features.size();j++)
01061 {
01062 float d = (hole_features[j].pt.x - hole_candidates[i].pt.x)*(hole_features[j].pt.x - hole_candidates[i].pt.x) +
01063 (hole_features[j].pt.y - hole_candidates[i].pt.y)*(hole_features[j].pt.y - hole_candidates[i].pt.y);
01064 if ((d < accuracy*accuracy*dist_coeff)&&(d<min_dist))
01065 {
01066 min_idx = j;
01067 min_dist = d;
01068 }
01069 }
01070 hole_candidates_repainted.push_back(hole_candidates[i]);
01071 if (min_idx>=0)
01072 hole_candidates_repainted[i].class_id = hole_features[min_idx].class_id;
01073 }
01074 }
01075
01076 float generalizedHoughTransform(vector<feature_t>& hole_candidates, const vector<feature_t>& train_features, int* hist_size, float** ranges,vector<outlet_t>& holes, IplImage* ghtImage, IplImage* resImage, char* output_path, char* base_filename)
01077 {
01078 const float max_error = (float)1e38;
01079 const int min_votes = 3;
01080
01081 IplImage* ght = 0;
01082 if (ghtImage)
01083 {
01084 ght = cvCloneImage(ghtImage);
01085 }
01086 CvSparseMat* hist = buildHoughHist(hole_candidates,train_features,hist_size,ranges);
01087 float** values = new float*[1];
01088 int count = 1;
01089 int votes = 0;
01090 votes = getMaxHistValues(hist,hist_size,ranges,values,count);
01091 #if defined(_VERBOSE)
01092 printf("Votes: %d\n",votes);
01093 #endif
01094 cvReleaseSparseMat(&hist);
01095
01096 if(votes < min_votes)
01097 {
01098 cvReleaseImage(&ght);
01099 return max_error;
01100 }
01101
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01138
01139 vector<feature_t> hole_features;
01140 vector<feature_t> hole_features_corrected;
01141 vector<feature_t> res_features;
01142
01143 float accuracy = sqrt((float)((train_features[1].pt.x -train_features[0].pt.x)*(train_features[1].pt.x -train_features[0].pt.x)+
01144 (train_features[1].pt.y -train_features[0].pt.y)*(train_features[1].pt.y -train_features[0].pt.y)));
01145 float error = (float)1e38;
01146 int index = -1;
01147
01148
01149
01150
01151 for (int j=0;j<count;j++)
01152 {
01153 float currError;
01154 hole_features.clear();
01155 calcOutletPosition(train_features, values[j],hole_features);
01156
01157
01158 if (ghtImage && (hole_features.size() > 0) && output_path && base_filename)
01159 {
01160 char path[1024];
01161 sprintf(path,"%s/%s_%d.jpg",output_path,base_filename,j);
01162 IplImage* tmp = cvCloneImage(ght);
01163
01164
01165
01166 for(int l = 0; l < (int)hole_features.size(); l++)
01167 {
01168
01169 CvScalar pointColor = hole_features[l].class_id == 0 ? cvScalar(0,255,50) : cvScalar(255,0,50);
01170 cvLine(tmp, cvPoint((int)(hole_features[l].pt.x+7), (int)(hole_features[l].pt.y)), cvPoint((int)(hole_features[l].pt.x-7),(int)(hole_features[l].pt.y)),pointColor,2);
01171 cvLine(tmp, cvPoint((int)(hole_features[l].pt.x), (int)(hole_features[l].pt.y+7)), cvPoint((int)(hole_features[l].pt.x), (int)(hole_features[l].pt.y-7)),pointColor,2);
01172 }
01173
01174
01175 cvSaveImage(path,tmp);
01176 cvReleaseImage(&tmp);
01177 }
01178
01179 if (ghtImage)
01180 {
01181 for(int i = 0; i < (int)hole_features.size(); i++)
01182 {
01183 CvScalar pointColor = hole_features[i].class_id == 0 ? cvScalar(0,255,50) : cvScalar(255,0,50);
01184 cvLine(ghtImage, cvPoint((int)(hole_features[i].pt.x+7), (int)(hole_features[i].pt.y)), cvPoint((int)(hole_features[i].pt.x-7),(int)(hole_features[i].pt.y)),pointColor,2);
01185 cvLine(ghtImage, cvPoint((int)(hole_features[i].pt.x), (int)(hole_features[i].pt.y+7)), cvPoint((int)(hole_features[i].pt.x), (int)(hole_features[i].pt.y-7)),pointColor,2);
01186
01187 }
01188 }
01189
01190 vector<feature_t> hole_candidates2;
01191 if (hole_features.size() >0)
01192 {
01193 repaintFeatures(hole_candidates, hole_features, hole_candidates2,(int)accuracy);
01194 }
01195 else
01196 {
01197 hole_candidates2 = hole_candidates;
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 #if 1
01210 calcExactLocation(hole_candidates2,train_features,hole_features,hole_features_corrected,currError,(int)accuracy);
01211 #else
01212 calcExactLocation(hole_candidates2,train_features,hole_features,hole_features_corrected,currError,(int)accuracy,false);
01213 #endif
01214
01215 if (currError < error)
01216 {
01217 index = j;
01218 error = currError;
01219 res_features.clear();
01220 for (int i =0; i< (int)hole_features_corrected.size(); i++)
01221 res_features.push_back(hole_features_corrected[i]);
01222 }
01223
01224
01225
01226 }
01227
01228 #if 1
01229 if (res_features.size() > 0)
01230 {
01231 filterOutletOutliers(hole_candidates,res_features,(int)accuracy);
01232 }
01233 #endif
01234
01235
01236 if ((int)(res_features.size()) > 0)
01237 {
01238 convertFeaturesToOutlet(res_features, holes, resImage);
01239 }
01240 else
01241 {
01242 error = max_error;
01243 }
01244
01245
01246 for (int i=0;i<count;i++)
01247 delete[] values[i];
01248 delete[] values;
01249 if (ghtImage)
01250 cvReleaseImage(&ght);
01251
01252 return error;
01253 }