00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "ObjRec/ObjRecBOF.H"
00039 #include "Component/OptionManager.H"
00040 #include "Image/ColorOps.H"
00041 #include "GUI/DebugWin.H"
00042 #include "Image/DrawOps.H"
00043 #include "Image/FilterOps.H"
00044 #include "Image/ImageSet.H"
00045 #include "Image/Kernels.H"
00046 #include "Image/MathOps.H"
00047 #include <dirent.h>
00048
00049
00050
00051
00052 ObjRecBOF::ObjRecBOF(OptionManager& mgr, const std::string& descrName,
00053 const std::string& tagName) :
00054 ModelComponent(mgr, descrName, tagName),
00055 itsNumOriArray(36)
00056 {
00057
00058 }
00059
00060 void ObjRecBOF::start2()
00061 {
00062
00063
00064 }
00065
00066 ObjRecBOF::~ObjRecBOF()
00067 {
00068 }
00069
00070
00071 void ObjRecBOF::train(const Image<PixRGB<byte> > &img, const std::string label)
00072 {
00073
00074 }
00075
00076 void ObjRecBOF::train(const std::string &name, int cls)
00077 {
00078
00079
00080
00081 getIlabSIFTKeypoints(name.c_str());
00082
00083 }
00084
00085 void ObjRecBOF::getSaliencyKeypoints(const std::string &name)
00086 {
00087
00088 char filename[255];
00089 const char* dirname = "/lab/tmpib/u/objRec/bof/salBayes/fv";
00090 snprintf(filename, sizeof(filename), "%s/%s.jpg.dat", dirname, name.c_str());
00091 Object obj;
00092 obj.name = name;
00093 obj.keypoints = readSaliencyKeypoints(filename);
00094 if (obj.keypoints.size() > 0)
00095 itsObjects.push_back(obj);
00096 }
00097
00098 void ObjRecBOF::getSIFTKeypoints(const std::string &name)
00099 {
00100
00101 char filename[255];
00102 const char* dirname = "/lab/tmpib/u/objRec/bof/siftDemoV4/voc/keyp";
00103 snprintf(filename, sizeof(filename), "%s/%s.jpg.dat", dirname, name.c_str());
00104 Object obj;
00105 obj.name = name;
00106 obj.keypoints = readSIFTKeypoints(filename);
00107 if (obj.keypoints.size() > 0)
00108 itsObjects.push_back(obj);
00109 }
00110
00111 void ObjRecBOF::getIlabSIFTKeypoints(const std::string &name)
00112 {
00113
00114 char filename[255];
00115 const char* dirname = "/home/elazary/images/VOCdevkit/VOC2007/ilabSift";
00116 snprintf(filename, sizeof(filename), "%s/%s.jpg.dat", dirname, name.c_str());
00117 Object obj;
00118 obj.name = name;
00119 obj.keypoints = readIlabSIFTKeypoints(filename);
00120 if (obj.keypoints.size() > 0)
00121 itsObjects.push_back(obj);
00122 }
00123
00124 void ObjRecBOF::finalizeTraining()
00125 {
00126 getCodeWords(200);
00127 printCodeWords();
00128
00129 }
00130
00131 void ObjRecBOF::finalizeTesting()
00132 {
00133 assignCodeWords();
00134 printAssignedCodeWords();
00135 }
00136
00137 void ObjRecBOF::getObjCodeWords(const std::string &name)
00138 {
00139 char filename[255];
00140 const char* dirname = "/home/elazary/images/VOCdevkit/VOC2007/ilabSift";
00141 snprintf(filename, sizeof(filename), "%s/%s.jpg.dat", dirname, name.c_str());
00142 Object obj;
00143 obj.name = name;
00144 obj.keypoints = readIlabSIFTKeypoints(filename);
00145 if (obj.keypoints.size() > 0)
00146 {
00147 for(uint kp=0; kp<obj.keypoints.size(); kp++)
00148 {
00149 int codeWord = assignCodeWord(obj.keypoints[kp].fv);
00150 obj.keypoints[kp].codeWord = codeWord;
00151 }
00152 }
00153
00154 snprintf(filename, sizeof(filename), "%s.dat", obj.name.c_str());
00155 FILE* fp = fopen(filename, "w");
00156 if (!fp)
00157 LFATAL("Error writing %s", obj.name.c_str());
00158
00159 for(uint kp=0; kp<obj.keypoints.size(); kp++)
00160 {
00161 fprintf(fp, "%f %f %i ",
00162 obj.keypoints[kp].x,
00163 obj.keypoints[kp].y,
00164 obj.keypoints[kp].codeWord);
00165
00166
00167 fprintf(fp, "\n");
00168 }
00169 fclose(fp);
00170
00171 }
00172
00173 Image<float> ObjRecBOF::extractFeatures(const Image<PixRGB<byte> > &img)
00174 {
00175 extractSIFTFeatures(img);
00176
00177
00178 return Image<float>();
00179 }
00180
00181 void ObjRecBOF::extractGaborFeatures(const Image<PixRGB<byte> > &img)
00182 {
00183
00184 int itsNumOri = 8;
00185 int itsNumScales = 2;
00186
00187 float stdmin = 1.75F;
00188 float stdstep = 0.5F;
00189 int fsmin = 3;
00190 int fsstep = 1;
00191
00192 ImageSet<float> itsFilters;
00193
00194 for(int scale = 0; scale < itsNumScales; scale++)
00195 for(int ori = 0; ori < itsNumOri; ori++)
00196 {
00197
00198 Image<float> filter = dogFilter<float>(stdmin + stdstep * scale,
00199 (float)ori * 180.0F / (float)itsNumOri,
00200 fsmin + fsstep * scale);
00201
00202
00203
00204 filter -= mean(filter);
00205
00206
00207
00208
00209 itsFilters.push_back(filter);
00210 }
00211
00212
00213 double normSum = 0;
00214 Image<float> input = luminance(img);
00215
00216 ImageSet<float> featuresValues(itsFilters.size());
00217 for(uint i=0; i<itsFilters.size(); i++)
00218 {
00219 Image<float> tmp = convolve(input, itsFilters[i], CONV_BOUNDARY_CLEAN);
00220
00221 tmp = abs(tmp);
00222 normSum += sum(tmp);
00223 featuresValues[i] = tmp;
00224 }
00225
00226
00227 for(uint feature=0; feature<featuresValues.size(); feature++)
00228 {
00229 Image<float> featureVal = featuresValues[feature];
00230
00231 std::vector<Histogram> levelHists;
00232 for(int level = 0; level < 4; level++)
00233 {
00234 int levelSize = 1<<level;
00235 Histogram hist(levelSize*levelSize);
00236
00237 int xSpace = (featureVal.getWidth()/levelSize) + 1;
00238 int ySpace = (featureVal.getHeight()/levelSize) + 1;
00239
00240 for(int y=0; y<featureVal.getHeight(); y++)
00241 for(int x=0; x<featureVal.getWidth(); x++)
00242 {
00243 int binPos = (int)(x/xSpace + levelSize*(y/ySpace));
00244 hist.addValue(binPos, featureVal.getVal(x,y));
00245 }
00246 hist.normalize(normSum);
00247 levelHists.push_back(hist);
00248 }
00249
00250
00251 printf("%i %i ",feature, (int)levelHists.size());
00252 for(uint h=0; h<levelHists.size(); h++)
00253 {
00254 Histogram hist = levelHists[h];
00255 for(uint i=0; i<hist.size(); i++)
00256 printf("%f ", hist[i]);
00257 }
00258 printf("\n");
00259
00260 }
00261
00262
00263
00264 }
00265
00266 void ObjRecBOF::extractSIFTFeatures(const Image<PixRGB<byte> > &img)
00267 {
00268
00269 Image<float> input = luminance(img);
00270 LINFO("Get sift vector");
00271 for(int y=10; y<input.getHeight()-10; y+=10)
00272 for(int x=10; x<input.getWidth()-10; x+=10)
00273 {
00274 std::vector<std::vector<byte> > sd = getSiftDescriptor(input, x,y,2);
00275 for(uint j=0; j<sd.size(); j++)
00276 {
00277 printf("%i %i ", x, y);
00278 for(uint i=0; i<sd[j].size(); i++)
00279 {
00280 printf("%i ", sd[j][i]);
00281 }
00282 printf("\n");
00283 }
00284 }
00285
00286 }
00287
00288
00289 void ObjRecBOF::extractCodeWords(const char* dirname)
00290 {
00291
00292 Image<float> debugImg(256,256, ZEROS);
00293 readSaliencyFeatures(dirname);
00294
00295
00296 for(uint obj=0; obj<itsObjects.size(); obj++)
00297 for(uint kp=0; kp<itsObjects[obj].keypoints.size(); kp++)
00298 {
00299 float x = itsObjects[obj].keypoints[kp].fv[0];
00300 float y = itsObjects[obj].keypoints[kp].fv[1];
00301
00302 debugImg.setVal((int)x,(int)y,128.0);
00303 }
00304
00305
00306 getCodeWords(200);
00307
00308
00309 for(uint j=0; j<itsCodeWords.size(); j++)
00310 {
00311 float x = itsCodeWords[j][0];
00312 float y = itsCodeWords[j][1];
00313
00314 drawCircle(debugImg, Point2D<int>((int)x,(int)y), 3, 255.0F);
00315 }
00316 SHOWIMG(debugImg);
00317
00318
00319
00320
00321 }
00322
00323 void ObjRecBOF::printFeatures()
00324 {
00325
00326 for (uint i=0; i<itsObjects[0].keypoints.size(); i++)
00327 {
00328 printf("%i %f %f ", i,
00329 itsObjects[0].keypoints[i].x,
00330 itsObjects[0].keypoints[i].y);
00331
00332 std::vector<double> fv = itsObjects[0].keypoints[i].fv;
00333 for (uint j=0; j<fv.size(); j++)
00334 printf("%f ", fv[j]);
00335 printf("\n");
00336 }
00337
00338 }
00339
00340 void ObjRecBOF::printCodeWords()
00341 {
00342
00343 for(uint j=0; j<itsCodeWords.size(); j++)
00344 {
00345 for(uint i=0; i<itsCodeWords[j].size(); i++)
00346 printf("%f ", itsCodeWords[j][i]);
00347 printf("\n");
00348 }
00349 }
00350
00351 void ObjRecBOF::printAssignedCodeWords()
00352 {
00353 for(uint obj=0; obj<itsObjects.size(); obj++)
00354 {
00355 char filename[255];
00356 snprintf(filename, sizeof(filename), "%s.dat", itsObjects[obj].name.c_str());
00357 FILE* fp = fopen(filename, "w");
00358 if (!fp)
00359 LFATAL("Error writing %s", itsObjects[obj].name.c_str());
00360
00361 for(uint kp=0; kp<itsObjects[obj].keypoints.size(); kp++)
00362 {
00363 fprintf(fp, "%f %f %i ",
00364 itsObjects[obj].keypoints[kp].x,
00365 itsObjects[obj].keypoints[kp].y,
00366 itsObjects[obj].keypoints[kp].codeWord);
00367
00368
00369 fprintf(fp, "\n");
00370 }
00371 fclose(fp);
00372 }
00373 }
00374
00375 void ObjRecBOF::assignCodeWords()
00376 {
00377 for(uint obj=0; obj<itsObjects.size(); obj++)
00378 for(uint kp=0; kp<itsObjects[obj].keypoints.size(); kp++)
00379 {
00380 int codeWord = assignCodeWord(itsObjects[obj].keypoints[kp].fv);
00381 itsObjects[obj].keypoints[kp].codeWord = codeWord;
00382 }
00383 }
00384
00385 int ObjRecBOF::assignCodeWord(const std::vector<double> &fv)
00386 {
00387 std::vector<double>::const_iterator s = fv.begin();
00388 int k_best = 0;
00389 double min_dist = std::numeric_limits<double>::max();
00390
00391
00392 for(uint k=0; k<itsCodeWords.size(); k++)
00393 {
00394 std::vector<double>::iterator c = itsCodeWords[k].begin();
00395 double dist = 0;
00396
00397 uint j = 0;
00398 for(; j<= itsCodeWords[k].size() - 4; j += 4)
00399 {
00400 double t0 = c[j] - s[j];
00401 double t1 = c[j+1] - s[j+1];
00402 dist += t0*t0 + t1*t1;
00403
00404 t0 = c[j+2] - s[j+2];
00405 t1 = c[j+3] - s[j+3];
00406 dist += t0*t0 + t1*t1;
00407 }
00408
00409 for( ; j < itsCodeWords[k].size(); j++ )
00410 {
00411 double t = c[j] - s[j];
00412 dist += t*t;
00413 }
00414
00415 if (min_dist > dist)
00416 {
00417 min_dist = dist;
00418 k_best = k;
00419 }
00420 }
00421
00422 return k_best;
00423 }
00424
00425 void ObjRecBOF::readCodeWords(const char* filename)
00426 {
00427 LINFO("Reading %s", filename);
00428 FILE *fp;
00429 fp = fopen(filename, "r");
00430 if (!fp)
00431 LFATAL("Error reading %s\n", filename);
00432
00433 int nCodeWords, nDim;
00434
00435 if (fscanf(fp, "%d %d", &nCodeWords, &nDim) != 2)
00436 LFATAL("Invalid codeword file beginning.");
00437
00438 itsCodeWords.clear();
00439 itsCodeWords.resize(nCodeWords);
00440 for (int i = 0; i < nCodeWords; i++) {
00441
00442 std::vector<double> codeWord(nDim);
00443
00444 for (int j = 0; j < nDim; j++) {
00445 float val;
00446 if (fscanf(fp, "%f", &val) != 1)
00447 LFATAL("Invalid code word.");
00448 codeWord[j] = val;
00449 }
00450 itsCodeWords[i] = codeWord;
00451 }
00452
00453 fclose(fp);
00454 }
00455
00456
00457 void ObjRecBOF::getCodeWords(int numCodeWords)
00458 {
00459
00460 initRandomNumbers();
00461
00462 int numOfKeypoints = 0;
00463 int nDims = 0;
00464
00465 for(uint i=0; i<itsObjects.size(); i++)
00466 {
00467 numOfKeypoints += itsObjects[i].keypoints.size();
00468 if (itsObjects[i].keypoints.size() > 0)
00469 nDims = itsObjects[i].keypoints[0].fv.size();
00470 }
00471 ASSERT(numOfKeypoints != 0 && nDims != 0);
00472
00473
00474 std::vector<std::vector<double> > centers(numCodeWords, std::vector<double>(nDims));
00475 std::vector<std::vector<double> > oldCenters(numCodeWords, std::vector<double>(nDims));
00476 std::vector<int> counters(numCodeWords);
00477
00478 std::vector<int> labels(numOfKeypoints);
00479
00480
00481 for(uint i=0; i<labels.size(); i++)
00482 labels[i] = randomUpToNotIncluding(numCodeWords);
00483
00484
00485 int maxIter = 10;
00486 double epsilon = 1.0;
00487 double max_dist = epsilon*2;
00488
00489 for(int iter = 0; iter < maxIter; iter++)
00490 {
00491
00492 for(uint j=0; j<centers.size(); j++)
00493 for(uint i=0; i<centers[j].size(); i++)
00494 centers[j][i] = 0;
00495
00496
00497 for(uint i=0; i<counters.size(); i++)
00498 counters[i] = 0;
00499
00500
00501 uint idx = 0;
00502 for(uint obj=0; obj<itsObjects.size(); obj++)
00503 {
00504 uint numKp = itsObjects[obj].keypoints.size();
00505 for (uint kp=0; kp<numKp; kp++)
00506 {
00507 std::vector<double>::iterator s = itsObjects[obj].keypoints[kp].fv.begin();
00508 uint k = labels[idx];
00509 std::vector<double>::iterator c = centers[k].begin();
00510
00511 int j;
00512 for(j=0; j<= (int)centers[k].size() - 4; j += 4)
00513 {
00514 double t0 = c[j] + s[j];
00515 double t1 = c[j+1] + s[j+1];
00516
00517 c[j] = t0;
00518 c[j+1] = t1;
00519
00520 t0 = c[j+2] + s[j+2];
00521 t1 = c[j+3] + s[j+3];
00522
00523 c[j+2] = t0;
00524 c[j+3] = t1;
00525 }
00526 for( ; j < (int)centers[k].size(); j++ )
00527 c[j] += s[j];
00528
00529 counters[k]++;
00530 idx++;
00531 }
00532 }
00533
00534 if (iter > 0)
00535 max_dist = 0;
00536
00537 for(uint k=0; k<centers.size(); k++)
00538 {
00539 std::vector<double>::iterator c = centers[k].begin();
00540 if (counters[k] != 0)
00541 {
00542
00543 double scale = 1./counters[k];
00544 for(uint j = 0; j < centers[k].size(); j++ )
00545 c[j] *= scale;
00546 }
00547 else
00548 {
00549
00550
00551 int obj = randomUpToNotIncluding(itsObjects.size());
00552 int kp = randomUpToNotIncluding(itsObjects[obj].keypoints.size());
00553
00554
00555 for(uint j=0; j<centers[k].size(); j++)
00556 c[j] = itsObjects[obj].keypoints[kp].fv[j];
00557 }
00558
00559 if (iter > 0)
00560 {
00561
00562 double dist = 0;
00563 std::vector<double>::iterator c_o = oldCenters[k].begin();
00564 for(uint j = 0; j < centers[k].size(); j++ )
00565 {
00566 double t = c[j] - c_o[j];
00567 dist += t*t;
00568 }
00569 if( max_dist < dist )
00570 max_dist = dist;
00571 }
00572 }
00573
00574
00575 idx = 0;
00576 for(uint obj=0; obj<itsObjects.size(); obj++)
00577 {
00578 uint numKp = itsObjects[obj].keypoints.size();
00579 for (uint kp=0; kp<numKp; kp++)
00580 {
00581 std::vector<double>::iterator s = itsObjects[obj].keypoints[kp].fv.begin();
00582 int k_best = 0;
00583 double min_dist = std::numeric_limits<double>::max();
00584
00585
00586 for(uint k=0; k<centers.size(); k++)
00587 {
00588 std::vector<double>::iterator c = centers[k].begin();
00589 double dist = 0;
00590
00591 int j = 0;
00592 for(; j<= (int)centers[k].size() - 4; j += 4)
00593 {
00594 double t0 = c[j] - s[j];
00595 double t1 = c[j+1] - s[j+1];
00596 dist += t0*t0 + t1*t1;
00597
00598 t0 = c[j+2] - s[j+2];
00599 t1 = c[j+3] - s[j+3];
00600 dist += t0*t0 + t1*t1;
00601 }
00602
00603 for( ; j < (int)centers[k].size(); j++ )
00604 {
00605 double t = c[j] - s[j];
00606 dist += t*t;
00607 }
00608
00609 if (min_dist > dist)
00610 {
00611 min_dist = dist;
00612 k_best = k;
00613 }
00614 }
00615 labels[idx] = k_best;
00616 idx++;
00617 }
00618 }
00619
00620 if (max_dist < epsilon)
00621 break;
00622
00623
00624 for(uint j=0; j<centers.size(); j++)
00625 {
00626 for(uint i=0; i<centers[j].size(); i++)
00627 {
00628 double tmp = centers[j][i];
00629 centers[j][i] = oldCenters[j][i];
00630 oldCenters[j][i] = tmp;
00631 }
00632 }
00633
00634 }
00635
00636
00637 for(uint i=0; i<counters.size(); i++)
00638 counters[i] = 0;
00639
00640 uint idx = 0;
00641 for(uint obj=0; obj<itsObjects.size(); obj++)
00642 {
00643 uint numKp = itsObjects[obj].keypoints.size();
00644 for (uint kp=0; kp<numKp; kp++)
00645 {
00646 counters[labels[idx]]++;
00647 idx++;
00648 }
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 itsCodeWords = centers;
00662
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
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 void ObjRecBOF::readSaliencyFeatures(const char* dirname)
00755 {
00756 DIR *dp = opendir(dirname);
00757 if (dp == NULL)
00758 LFATAL("Can not open %s", dirname);
00759 dirent *dirp;
00760 while ((dirp = readdir(dp)) != NULL ) {
00761 std::string dirName(dirp->d_name);
00762 if (dirName.find(".dat") != std::string::npos)
00763 {
00764 char filename[255];
00765 snprintf(filename, sizeof(filename), "%s/%s", dirname, dirp->d_name);
00766 Object obj;
00767 obj.name = std::string(dirp->d_name);
00768 obj.keypoints = readSaliencyKeypoints(filename);
00769 itsObjects.push_back(obj);
00770 }
00771 }
00772 closedir(dp);
00773 }
00774
00775 std::vector<ObjRecBOF::Keypoint> ObjRecBOF::readSaliencyKeypoints(const char *filename)
00776 {
00777
00778 std::vector<Keypoint> keypoints;
00779 LINFO("Reading %s", filename);
00780 FILE *fp;
00781 fp = fopen(filename, "r");
00782 if (!fp)
00783 {
00784 LINFO("Error reading %s", filename);
00785 return keypoints;
00786 }
00787
00788 int len = 42;
00789 while (fp != NULL)
00790 {
00791 Keypoint key;
00792 int keyNum, x, y;
00793 if (fscanf(fp, "%i %i %i", &keyNum, &x, &y) != 3) break;
00794 key.x = (double)x;
00795 key.y = (double)y;
00796 key.codeWord = -1;
00797
00798 for (int j = 0; j < len; j++) {
00799 float val = -1;
00800 if (fscanf(fp, "%f", &val) != 1)
00801 perror("Invalid keypoint file value.");
00802 key.fv.push_back(val);
00803 }
00804 keypoints.push_back(key);
00805 }
00806
00807 fclose(fp);
00808 return keypoints;
00809 }
00810
00811 std::vector<ObjRecBOF::Keypoint> ObjRecBOF::readSIFTKeypoints(const char *filename)
00812 {
00813
00814 std::vector<Keypoint> keypoints;
00815 printf("Reading %s\n", filename);
00816 FILE *fp;
00817 fp = fopen(filename, "r");
00818 if (!fp)
00819 {
00820 LINFO("Error reading %s", filename);
00821 return keypoints;
00822 }
00823
00824 int i, j, num, len, val;
00825
00826 if (fscanf(fp, "%d %d", &num, &len) != 2)
00827 perror("Invalid keypoint file beginning.");
00828
00829 if (len != 128)
00830 perror("Keypoint descriptor length invalid (should be 128).");
00831 for (i = 0; i < num; i++) {
00832
00833 Keypoint key;
00834 float x, y, scale, ori;
00835 if (fscanf(fp, "%f %f %f %f", &x, &y, &scale, &ori) != 4) break;
00836 key.x = x;
00837 key.y = y;
00838 key.scale = scale;
00839 key.ori = ori;
00840
00841 for (j = 0; j < len; j++) {
00842 if (fscanf(fp, "%d", &val) != 1 || val < 0 || val > 255)
00843 perror("Invalid keypoint file value.");
00844 key.fv.push_back((double)val);
00845 }
00846 keypoints.push_back(key);
00847 }
00848
00849 fclose(fp);
00850
00851 return keypoints;
00852 }
00853
00854 std::vector<ObjRecBOF::Keypoint> ObjRecBOF::readIlabSIFTKeypoints(const char *filename)
00855 {
00856
00857 std::vector<Keypoint> keypoints;
00858 printf("Reading %s\n", filename);
00859 FILE *fp;
00860 fp = fopen(filename, "r");
00861 if (!fp)
00862 {
00863 LINFO("Error reading %s", filename);
00864 return keypoints;
00865 }
00866
00867 int len = 128;
00868
00869 while (fp != NULL)
00870 {
00871 Keypoint key;
00872 int x, y;
00873 if (fscanf(fp, "%i %i", &x, &y) != 2) break;
00874 key.x = x;
00875 key.y = y;
00876
00877 for (int j = 0; j < len; j++) {
00878 int val;
00879 if (fscanf(fp, "%d", &val) != 1 || val < 0 || val > 255)
00880 perror("Invalid keypoint file value.");
00881 key.fv.push_back((double)val);
00882 }
00883 keypoints.push_back(key);
00884 }
00885
00886 fclose(fp);
00887
00888 return keypoints;
00889 }
00890
00891 std::vector<std::vector<byte> > ObjRecBOF::getSiftDescriptor(const Image<float> &lum,
00892 const float x, const float y, const float s)
00893 {
00894
00895 Image<float> mag, ori;
00896
00897
00898 gradient(lum, mag, ori);
00899
00900 Histogram OV(itsNumOriArray);
00901
00902
00903 calculateOrientationVector(x, y, s, mag, ori, OV);
00904
00905
00906
00907
00908
00909 return createVectorsAndKeypoints(x, y, s, mag, ori, OV);
00910
00911 }
00912
00913 void ObjRecBOF::calculateOrientationVector(const float x, const float y, const float s,
00914 const Image<float>& gradmag, const Image<float>& gradorie, Histogram& OV) {
00915
00916
00917
00918
00919 const float sigma = s;
00920
00921 const float sig = 1.5F * sigma, inv2sig2 = - 0.5F / (sig * sig);
00922 const int dimX = gradmag.getWidth(), dimY = gradmag.getHeight();
00923
00924 const int xi = int(x + 0.5f);
00925 const int yi = int(y + 0.5f);
00926
00927 const int rad = int(3.0F * sig);
00928 const int rad2 = rad * rad;
00929
00930
00931
00932 int starty = yi - rad; if (starty < 0) starty = 0;
00933 int stopy = yi + rad; if (stopy >= dimY) stopy = dimY-1;
00934
00935
00936 for (int ind_y = starty; ind_y <= stopy; ind_y ++)
00937 {
00938
00939
00940 const int yoff = ind_y - yi;
00941 const int bound = int(sqrtf(float(rad2 - yoff*yoff)) + 0.5F);
00942 int startx = xi - bound; if (startx < 0) startx = 0;
00943 int stopx = xi + bound; if (stopx >= dimX) stopx = dimX-1;
00944
00945 for (int ind_x = startx; ind_x <= stopx; ind_x ++)
00946 {
00947 const float dx = float(ind_x) - x, dy = float(ind_y) - y;
00948 const float distSq = dx * dx + dy * dy;
00949
00950
00951 const float gradVal = gradmag.getVal(ind_x, ind_y);
00952
00953
00954 const float gaussianWeight = expf(distSq * inv2sig2);
00955
00956
00957
00958 float angle = gradorie.getVal(ind_x, ind_y) + M_PI;
00959
00960
00961 angle = 0.5F * angle * itsNumOriArray / M_PI;
00962 while (angle < 0.0F) angle += itsNumOriArray;
00963 while (angle >= itsNumOriArray) angle -= itsNumOriArray;
00964
00965 OV.addValueInterp(angle, gaussianWeight * gradVal);
00966 }
00967 }
00968
00969
00970
00971 for (int i = 0; i < 3; i++) OV.smooth();
00972 }
00973
00974
00975
00976
00977 std::vector<std::vector<byte> > ObjRecBOF::createVectorsAndKeypoints(const float x,
00978 const float y, const float s,
00979 const Image<float>& gradmag, const Image<float>& gradorie, Histogram& OV)
00980 {
00981
00982 const float sigma = s;
00983
00984
00985 float maxPeakValue = OV.findMax();
00986
00987 const int xi = int(x + 0.5f);
00988 const int yi = int(y + 0.5f);
00989
00990 uint numkp = 0;
00991
00992 std::vector<std::vector<byte> > descriptor;
00993
00994
00995
00996 for (int bin = 0; bin < itsNumOriArray; bin++)
00997 {
00998
00999 const float midval = OV.getValue(bin);
01000
01001
01002 if (midval == 0 || midval < 0.8F * maxPeakValue) continue;
01003
01004
01005 const float leftval = OV.getValue((bin == 0) ? itsNumOriArray-1 : bin-1);
01006
01007
01008 const float rightval = OV.getValue((bin == itsNumOriArray-1) ? 0 : bin+1);
01009
01010
01011 if (leftval > midval) continue;
01012 if (rightval > midval) continue;
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023 const float a = 0.5f * (leftval + rightval) - midval;
01024 const float b = 0.5f * (rightval - leftval);
01025 float realangle = float(bin) - 0.5F * b / a;
01026
01027 realangle *= 2.0F * M_PI / itsNumOriArray;
01028 realangle -= M_PI;
01029
01030
01031
01032
01033 FeatureVector fv;
01034
01035 const float sinAngle = sin(realangle), cosAngle = cos(realangle);
01036
01037
01038 const int radius = int(5.0F * sigma + 0.5F);
01039 const float gausssig = float(radius);
01040 const float gaussfac = - 0.5F / (gausssig * gausssig);
01041
01042
01043
01044
01045
01046
01047
01048
01049 int scale = abs(int(s));
01050 scale = scale > 5 ? 5 : scale;
01051
01052 for (int ry = -radius; ry <= radius; ry++)
01053 for (int rx = -radius; rx <= radius; rx++)
01054 {
01055
01056 const float newX = rx * cosAngle - ry * sinAngle;
01057 const float newY = rx * sinAngle + ry * cosAngle;
01058
01059
01060 const float orgX = newX + float(xi);
01061 const float orgY = newY + float(yi);
01062
01063
01064 if (gradmag.coordsOk(orgX, orgY) == false) continue;
01065
01066
01067
01068 const float xf = 2.0F + 2.0F * float(rx) / float(radius);
01069 const float yf = 2.0F + 2.0F * float(ry) / float(radius);
01070
01071
01072
01073
01074 const float gaussFactor = expf((newX*newX+newY*newY) * gaussfac);
01075 const float weightedMagnitude =
01076 gaussFactor * gradmag.getValInterp(orgX, orgY);
01077
01078
01079
01080 float gradAng = gradorie.getValInterp(orgX, orgY) - realangle;
01081
01082 gradAng=fmod(gradAng, 2*M_PI);
01083
01084
01085 if (gradAng < 0.0) gradAng+=2*M_PI;
01086 if (gradAng >= M_PI) gradAng-=2*M_PI;
01087
01088 const float orient = (gradAng + M_PI) * 8 / (2 * M_PI);
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099 fv.addValue(xf, yf, orient, weightedMagnitude);
01100
01101 }
01102
01103
01104 std::vector<byte> oriVec;
01105
01106 fv.toByteKey(oriVec);
01107
01108 double mag = fv.getMag();
01109 if (oriVec.size() > 0 && mag > 0)
01110 descriptor.push_back(oriVec);
01111
01112
01113 ++ numkp;
01114
01115 }
01116 return descriptor;
01117 }
01118
01119
01120 std::string ObjRecBOF::test(const Image<PixRGB<byte> > &img)
01121 {
01122
01123
01124 return std::string("Test");
01125 }
01126
01127
01128
01129
01130
01131
01132