00001
00008 #include <blort/Recognizer3D/KeypointDescriptor.hh>
00009
00010
00011 namespace P
00012 {
00013
00014 float KeypointDescriptor::DOG_SIFT_THR = .2;
00015 float KeypointDescriptor::LOWE_DOG_SIFT_THR = 50000;
00016 float KeypointDescriptor::MSER_SIFT_THR = 40000;
00017 float KeypointDescriptor::HESLAP_SIFT_THR = 30000;
00018
00019 const unsigned KeypointDescriptor::KEDE_DELETE = 0x01;
00020 const unsigned KeypointDescriptor::KEDE_INSERT = 0x02;
00021 const unsigned KeypointDescriptor::KEDE_DETECTED = 0x04;
00022
00023
00024 static const int NAME_LENGTH = 40;
00025 static const char keyd_type_names[][NAME_LENGTH] = {
00026 "DOG_SIFT",
00027 "LOWE_DOG_SIFT",
00028 "MSER_SIFT",
00029 "UVMSER_SIFT",
00030 "HESLAP_SIFT",
00031 "UNDEF"
00032 };
00033
00037 const char* KeypointDescriptor::TypeName(Type t)
00038 {
00039 return keyd_type_names[t];
00040 }
00041
00045 KeypointDescriptor::Type KeypointDescriptor::EnumType(const char *type_name)
00046 {
00047 for(int i = 0; i < MAX_TYPE; i++)
00048 if(strncmp(type_name, keyd_type_names[i], NAME_LENGTH) == 0)
00049 return (Type)i;
00050 return UNDEF;
00051 }
00052
00053
00054
00058 KeypointDescriptor::KeypointDescriptor()
00059 : flags(0),
00060 type(UNDEF),
00061 vec(0),
00062 size(0),
00063 pos(0),
00064 cnt_pos(0),
00065 mask(0),
00066 bgmask(0),
00067 patch(0),
00068 reliability(1),
00069 cnt_rel(1),
00070 mean_error(0),
00071 var_error(0),
00072 cnt_err(0),
00073
00074 occNum(1),
00075 chainId(UINT_MAX),
00076 chainCnt(0)
00077 {
00078 p_rect = P::Vector2(0.,0.);
00079 }
00080
00081 KeypointDescriptor::KeypointDescriptor(Type t)
00082 : flags(0),
00083 type(t),
00084 vec(0),
00085 size(0),
00086 pos(0),
00087 cnt_pos(0),
00088 mask(0),
00089 bgmask(0),
00090 patch(0),
00091 reliability(1),
00092 cnt_rel(1),
00093 mean_error(0),
00094 var_error(0),
00095 cnt_err(0),
00096
00097 occNum(1),
00098 chainId(UINT_MAX),
00099 chainCnt(0)
00100 {
00101 p_rect = P::Vector2(0.,0.);
00102
00103 }
00104
00105
00106 KeypointDescriptor::~KeypointDescriptor()
00107 {
00108 if (vec!=0) delete[] vec;
00109 if (mask!=0) cvReleaseImage(&mask);
00110 if (bgmask!=0) cvReleaseImage(&bgmask);
00111 if (patch!=0) cvReleaseImage(&patch);
00112 if (pos!=0) cvReleaseMat(&pos);
00113 }
00114
00115 KeypointDescriptor::KeypointDescriptor(KeypointDescriptor *k)
00116 : Keypoint(*k),
00117 flags(0),
00118 vec(0),
00119 size(0),
00120 pos(0),
00121 cnt_pos(0),
00122 mask(0),
00123 bgmask(0),
00124 patch(0)
00125 {
00126 Copy(k);
00127 }
00128
00129 KeypointDescriptor::KeypointDescriptor(Type t, double x, double y, float s, float a)
00130 : Keypoint(x, y, s, a),
00131 flags(0),
00132 type(t),
00133 vec(0),
00134 size(0),
00135 pos(0),
00136 cnt_pos(0),
00137 mask(0),
00138 bgmask(0),
00139 patch(0),
00140 reliability(1),
00141 cnt_rel(1),
00142 mean_error(0),
00143 var_error(0),
00144 cnt_err(0),
00145
00146 occNum(1),
00147 chainId(UINT_MAX),
00148 chainCnt(0)
00149 {
00150 p_rect = P::Vector2(0.,0.);
00151 }
00152
00153 KeypointDescriptor::KeypointDescriptor(Type t, double x, double y, float s, float a,
00154 float _m11,float _m12,float _m21,float _m22)
00155 : Keypoint(x, y, s, a, _m11, _m12, _m21, _m22),
00156 flags(0),
00157 type(t),
00158 vec(0),
00159 size(0),
00160 pos(0),
00161 cnt_pos(0),
00162 mask(0),
00163 bgmask(0),
00164 patch(0),
00165 reliability(1),
00166 cnt_rel(1),
00167 mean_error(0),
00168 var_error(0),
00169 cnt_err(0),
00170
00171 occNum(1),
00172 chainId(UINT_MAX),
00173 chainCnt(0)
00174 {
00175 p_rect = P::Vector2(0.,0.);
00176 }
00177
00181 bool KeypointDescriptor::GetVoteCenter(KeypointDescriptor *current,Vector2 &v,
00182 double &delta_angle, double &delta_scale)
00183 {
00184 if (type==current->type){
00185 delta_scale = current->Scale()/Scale();
00186 delta_angle = ScaleAngle_mpi_pi(-Angle() + current->Angle());
00187 v = current->p + Rotate(-p,delta_angle)*delta_scale;
00188 return true;
00189 }
00190 return false;
00191 }
00192
00196 void KeypointDescriptor::SaveMask(IplImage *img)
00197 {
00198 if (!mask) mask = cvCreateImage( cvSize(PATCH_MASK_SIZE,PATCH_MASK_SIZE), IPL_DEPTH_32F, 1 );
00199 if (!bgmask) bgmask = cvCreateImage( cvSize(PATCH_MASK_SIZE,PATCH_MASK_SIZE), IPL_DEPTH_32F, 1 );
00200
00201 float sxy=(Scale()*6/PATCH_MASK_SIZE);
00202 CvMat* G = cvCreateMat(2,3,CV_32FC1);
00203
00204 float coso = cos(-Angle())*sxy;
00205 float sino = sin(-Angle())*sxy;
00206
00207 G->data.fl[0] = mi11*coso-mi12*sino;
00208 G->data.fl[1] = mi11*sino+mi12*coso;
00209 G->data.fl[2] = X();
00210 G->data.fl[3] = mi21*coso-mi22*sino;
00211 G->data.fl[4] = mi21*sino+mi22*coso;
00212 G->data.fl[5] = Y();
00213
00214 cvGetQuadrangleSubPix( img, mask, G );
00215 cvConvertScale(mask, bgmask, -1, 1 );
00216
00217 cvReleaseMat(&G);
00218 }
00219
00223 void KeypointDescriptor::ProjectMask(KeypointDescriptor *model,IplImage *img, float w)
00224 {
00225 float delta=-PATCH_MASK_SIZE/2.;
00226 float sxy=(Scale()*6/PATCH_MASK_SIZE);
00227 float coso = cos(-Angle())*sxy;
00228 float sino = sin(-Angle())*sxy;
00229
00230 CvMat* G= cvCreateMat(2,3,CV_32FC1);
00231 IplImage *wmask = cvCreateImage( cvSize(PATCH_MASK_SIZE,PATCH_MASK_SIZE), IPL_DEPTH_32F, 1 );
00232 cvConvertScale(model->mask,wmask,w,0);
00233
00234 G->data.fl[0] = mi11*coso-mi12*sino;
00235 G->data.fl[1] = mi11*sino+mi12*coso;
00236 G->data.fl[2] = delta*G->data.fl[0] + delta*G->data.fl[1] + p.x;
00237 G->data.fl[3] = mi21*coso-mi22*sino;
00238 G->data.fl[4] = mi21*sino+mi22*coso;
00239 G->data.fl[5] = delta*G->data.fl[4] + delta*G->data.fl[3] + p.y;
00240
00241
00242
00243 cvReleaseMat(&G);
00244 cvReleaseImage(&wmask);
00245 }
00246
00250 void KeypointDescriptor::ProjectBgMask(KeypointDescriptor *model,IplImage *img, float w)
00251 {
00252 float delta=-PATCH_MASK_SIZE/2.;
00253 float sxy=(Scale()*6/PATCH_MASK_SIZE);
00254 float coso = cos(-Angle())*sxy;
00255 float sino = sin(-Angle())*sxy;
00256
00257 CvMat* G= cvCreateMat(2,3,CV_32FC1);
00258 IplImage *wmask = cvCreateImage( cvSize(PATCH_MASK_SIZE,PATCH_MASK_SIZE), IPL_DEPTH_32F, 1 );
00259 cvConvertScale(model->bgmask,wmask,w,0);
00260
00261 G->data.fl[0] = mi11*coso-mi12*sino;
00262 G->data.fl[1] = mi11*sino+mi12*coso;
00263 G->data.fl[2] = delta*G->data.fl[0] + delta*G->data.fl[1] + p.x;
00264 G->data.fl[3] = mi21*coso-mi22*sino;
00265 G->data.fl[4] = mi21*sino+mi22*coso;
00266 G->data.fl[5] = delta*G->data.fl[4] + delta*G->data.fl[3] + p.y;
00267
00268
00269
00270 cvReleaseMat(&G);
00271 cvReleaseImage(&wmask);
00272 }
00273
00278 void KeypointDescriptor::ProjectOccl(P::Vector2 ¢er, float scale, float angle,
00279 IplImage *img, float w)
00280 {
00281 float delta=-PATCH_MASK_SIZE/2.;
00282 float sxy=(Scale()*6/PATCH_MASK_SIZE);
00283 float coso = cos(ScaleAngle_mpi_pi(-Angle()))*sxy*scale;
00284 float sino = sin(ScaleAngle_mpi_pi(-Angle()))*sxy*scale;
00285 P::Vector2 v = center + Rotate(p,angle)*scale;
00286
00287 CvMat* G= cvCreateMat(2,3,CV_32FC1);
00288 IplImage *wmask = cvCreateImage( cvSize(PATCH_MASK_SIZE,PATCH_MASK_SIZE), IPL_DEPTH_32F, 1 );
00289 cvConvertScale(mask,wmask,w,0);
00290
00291 G->data.fl[0] = mi11*coso-mi12*sino;
00292 G->data.fl[1] = mi11*sino+mi12*coso;
00293 G->data.fl[2] = delta*G->data.fl[0] + delta*G->data.fl[1] + v.x;
00294 G->data.fl[3] = mi21*coso-mi22*sino;
00295 G->data.fl[4] = mi21*sino+mi22*coso;
00296 G->data.fl[5] = delta*G->data.fl[3] + delta*G->data.fl[4] + v.y;
00297
00298
00299
00300 cvReleaseMat(&G);
00301 cvReleaseImage(&wmask);
00302 }
00303
00307 #ifdef SAVE_PATCHES
00308 static unsigned mcnt=0;
00309 char fname[1024];
00310 #endif
00311 void KeypointDescriptor::SavePatch(IplImage *img)
00312 {
00313 if (!patch) patch = cvCreateImage( cvSize(PATCH_MASK_SIZE,PATCH_MASK_SIZE), IPL_DEPTH_8U, 1 );
00314
00315 float sxy=(Scale()*6/PATCH_MASK_SIZE);
00316 CvMat* G = cvCreateMat(2,3,CV_32FC1);
00317
00318 float coso = cos(-Angle())*sxy;
00319 float sino = sin(-Angle())*sxy;
00320
00321 G->data.fl[0] = mi11*coso-mi12*sino;
00322 G->data.fl[1] = mi11*sino+mi12*coso;
00323 G->data.fl[2] = X();
00324 G->data.fl[3] = mi21*coso-mi22*sino;
00325 G->data.fl[4] = mi21*sino+mi22*coso;
00326 G->data.fl[5] = Y();
00327
00328 cvGetQuadrangleSubPix( img, patch, G );
00329
00330 cvReleaseMat(&G);
00331 #ifdef SAVE_PATCHES
00332 snprintf(fname,1024,"log/patch_%04u.png",mcnt);
00333 cvSaveImage(fname,patch);
00334 mcnt++;
00335 #endif
00336 }
00337
00341 void KeypointDescriptor::ProjectPatch(KeypointDescriptor *model,IplImage *img)
00342 {
00343 if (model->patch != 0){
00344 float delta=-PATCH_MASK_SIZE/2.;
00345 float sxy=(Scale()*6/PATCH_MASK_SIZE);
00346 float coso = cos(-Angle())*sxy;
00347 float sino = sin(-Angle())*sxy;
00348
00349 CvMat* G= cvCreateMat(2,3,CV_32FC1);
00350
00351 G->data.fl[0] = mi11*coso-mi12*sino;
00352 G->data.fl[1] = mi11*sino+mi12*coso;
00353 G->data.fl[2] = delta*G->data.fl[0] + delta*G->data.fl[1] + p.x;
00354 G->data.fl[3] = mi21*coso-mi22*sino;
00355 G->data.fl[4] = mi21*sino+mi22*coso;
00356 G->data.fl[5] = delta*G->data.fl[3] + delta*G->data.fl[4] + p.y;
00357
00358 cvWarpAffine( model->patch, img, G,CV_INTER_LINEAR);
00359
00360 cvReleaseMat(&G);
00361 }
00362 }
00363
00367 float KeypointDescriptor::Match(KeypointDescriptor *k)
00368 {
00369 if (GetType() == k->GetType()){
00370
00371 float dist;
00372
00373
00374 switch(GetType())
00375 {
00376 case DOG_SIFT:
00377 MatchSift(k, DOG_SIFT_THR, dist);
00378 break;
00379 case LOWE_DOG_SIFT:
00380 MatchSift(k, LOWE_DOG_SIFT_THR, dist);
00381 break;
00382 case MSER_SIFT:
00383 MatchSift(k, MSER_SIFT_THR, dist);
00384 break;
00385 case UVMSER_SIFT:
00386 MatchSift(k, MSER_SIFT_THR, dist);
00387 break;
00388 case HESLAP_SIFT:
00389 MatchSift(k, HESLAP_SIFT_THR, dist);
00390 break;
00391 default:
00392 dist = FLT_MAX;
00393 break;
00394 }
00395 return dist;
00396 }
00397 return FLT_MAX;
00398 }
00399
00403 void KeypointDescriptor::Draw(IplImage *img, KeypointDescriptor &k, CvScalar col)
00404 {
00405 double scale = k.Scale()*3;
00406 double U[4], D[4], Vi[4], V[4];
00407 CvMat matU = cvMat(2,2, CV_64F, U);
00408 CvMat matD = cvMat(2,2, CV_64F, D);
00409 CvMat matVi = cvMat(2,2, CV_64F, Vi);
00410 CvMat matV = cvMat(2,2, CV_64F, V);
00411
00412 U[0] = k.Mi11(), U[1] = k.Mi12();
00413 U[2] = k.Mi21(), U[3] = k.Mi22();
00414
00415 cvSVD(&matU, &matD, &matVi, &matV);
00416
00417 D[0] *= scale;
00418 D[1] *= scale;
00419 D[2] *= scale;
00420 D[3] *= scale;
00421
00422 double angle = ScaleAngle_0_2pi(acos(V[0]))*180./M_PI;
00423 SDraw::DrawEllipse(img, k.X(), k.Y(), D[0], D[3],angle, col);
00424 Vector2 v = Vector2(D[3],0);
00425 v = Rotate(v,-k.Angle());
00426 v = Vector2(v.x+k.X(), v.y+k.Y());
00427 SDraw::DrawLine(img, k.X(), k.Y(), v.x, v.y, col);
00428
00429 }
00430
00434 void KeypointDescriptor::ReadKeypoint( ifstream &in )
00435 {
00436 float tmp;
00437
00438 in >> p.x;
00439 in >> p.y;
00440 in >> tmp;
00441 in >> scale;
00442 in >> angle;
00443 in >> tmp;
00444 in >> tmp;
00445 in >> tmp;
00446 in >> tmp;
00447 in >> mi11;
00448 in >> mi12;
00449 in >> mi21;
00450 in >> mi22;
00451 }
00452
00453 void KeypointDescriptor::ReadDescriptor( ifstream &in, unsigned size_in)
00454 {
00455 if(size_in>0){
00456 AllocVec(size_in);
00457 for(unsigned j=0; j<size;j++){
00458 in >> vec[j];
00459 }
00460 }
00461 }
00462
00463 void KeypointDescriptor::WriteKeypoint( ofstream &out )
00464 {
00465 out << p.x << " " << p.y << " " << 0 << " " << scale << " ";
00466 out << angle<< " "<< type << " " << 0 << " " <<0<< " " <<0;
00467 out << " " << mi11 << " " << mi12 << " " << mi21 << " " << mi22<< " ";
00468 }
00469
00470 void KeypointDescriptor::WriteDescriptor(ofstream &out )
00471 {
00472 if(size>0){
00473 for(unsigned j=0; j<size;j++){
00474 out << vec[j] << " ";
00475 }
00476 }
00477 }
00478
00479 void WriteKeypoints(P::Array<KeypointDescriptor*> &ks, const char* file, int format)
00480 {
00481 if (ks.Size()==0){
00482 cout << " Keypoints Nb: " << ks.Size() << endl;
00483 return;
00484 }
00485 ofstream output(file);
00486 if(!output)cout << "Error opening " << file<< endl;
00487 output << ks[0]->GetSize()<< endl;
00488 output << ks.Size()<< endl;
00489 for(unsigned i=0; i<ks.Size();i++){
00490 if(format==0){
00491 ks[i]->WriteKeypoint(output);
00492 ks[i]->WriteDescriptor(output);
00493 output<<endl;
00494 }
00495 }
00496 output.close();
00497 }
00498
00499 void LoadKeypoints(const char* file, P::Array<KeypointDescriptor*> &ks, int format)
00500 {
00501 KeypointDescriptor* k;
00502 ifstream input1(file);
00503
00504 if(!input1)return;
00505
00506 unsigned numip, size;
00507 float tmp;
00508 input1 >> tmp;
00509 input1 >> numip;
00510 if(tmp<=1.0) size=0;
00511 else size=(int)tmp;
00512 for (unsigned i=0; i<numip; i++){
00513 if(format==0){
00514 k = new KeypointDescriptor();
00515 k->ReadKeypoint(input1);
00516 k->ReadDescriptor(input1, size);
00517 ks.PushBack(k);
00518 }
00519 }
00520
00521 input1.close();
00522 }
00523
00524 void LoadLoweKeypoints(const char* file, P::Array<Keypoint*> &ks, int format)
00525 {
00526 KeypointDescriptor* k;
00527 ifstream input1(file);
00528
00529 if(!input1)return;
00530
00531 unsigned numip, size;
00532 float tmp;
00533 input1 >> numip;
00534 input1 >> tmp;
00535 if(tmp<=1.0) size=0;
00536 else size=(int)tmp;
00537 for (unsigned i=0; i<numip; i++){
00538 if(format==0){
00539 k = new KeypointDescriptor();
00540 input1 >> k->p.y;
00541 input1 >> k->p.x;
00542 input1 >> k->scale;
00543 input1 >> k->angle;
00544 k->angle = -k->angle;
00545 k->ReadDescriptor(input1, size);
00546 ks.PushBack(k);
00547 }
00548 }
00549
00550 input1.close();
00551 }
00552
00553 void LoadLoweKeypoints(const char* file, P::Array<KeypointDescriptor*> &ks, int format)
00554 {
00555 KeypointDescriptor* k;
00556 ifstream input1(file);
00557
00558 if(!input1)return;
00559
00560 unsigned numip, size;
00561 float tmp;
00562 input1 >> numip;
00563 input1 >> tmp;
00564 if(tmp<=1.0) size=0;
00565 else size=(int)tmp;
00566 for (unsigned i=0; i<numip; i++){
00567 if(format==0){
00568 k = new KeypointDescriptor();
00569 input1 >> k->p.y;
00570 input1 >> k->p.x;
00571 input1 >> k->scale;
00572 input1 >> k->angle;
00573 k->angle = -k->angle;
00574 k->ReadDescriptor(input1, size);
00575 ks.PushBack(k);
00576 }
00577 }
00578
00579 input1.close();
00580 }
00581
00582
00583 void KeypointDescriptor::SaveAll(ofstream &os, const KeypointDescriptor &k)
00584 {
00585 os << k.p.x<<' '<<k.p.y<<' '<<k.scale<<' '<<k.angle;
00586 os <<' '<<k.mi11<<' '<<k.mi12<<' '<<k.mi21<<' '<<k.mi22;
00587 os <<' '<<k.flags<<' '<<k.type<<' '<<k.size;
00588 for (unsigned i=0; i<k.size; i++)
00589 os <<' '<<k.vec[i];
00590 if (k.pos!=0)
00591 os <<' '<<'1'<<' '<<(float)k.pos->data.fl[0]<<' '<<(float)k.pos->data.fl[1]<<' '<<(float)k.pos->data.fl[2];
00592 else
00593 os <<' '<<'0';
00594 os<<' '<<k.cnt_pos<<' '<<k.p_rect.x<<' '<<k.p_rect.y<<' ';
00595 os<<' '<<k.reliability<<' '<<k.cnt_rel;
00596 os<<' '<<k.mean_error<<' '<<k.var_error<<' '<<k.var_error<<' '<<k.cnt_err;
00597 os<<'\n';
00598 }
00599
00600 void KeypointDescriptor::LoadAll(ifstream &is, KeypointDescriptor &k)
00601 {
00602 is >> k.p.x>>k.p.y>>k.scale>>k.angle>>k.mi11>>k.mi12>>k.mi21>>k.mi22;
00603 unsigned type;
00604 is >>k.flags>>type>>k.size;
00605 k.type = (KeypointDescriptor::Type)type;
00606 k.AllocVec(k.size);
00607 for (unsigned i=0; i<k.size; i++)
00608 is >>k.vec[i];
00609 unsigned c;
00610 is>>c;
00611 if (c==1)
00612 {
00613 if (k.pos==0) k.pos = cvCreateMat(3,1, CV_32F);
00614 is>>k.pos->data.fl[0]>>k.pos->data.fl[1]>>k.pos->data.fl[2];
00615 }
00616 is>>k.cnt_pos>>k.p_rect.x>>k.p_rect.y;
00617 is>>k.reliability>>k.cnt_rel;
00618 is>>k.mean_error>>k.var_error>>k.var_error>>k.cnt_err;
00619 }
00620
00621
00622
00623
00624
00625
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638