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
00039 #ifndef GeometricHashing_C_DEFINED
00040 #define GeometricHashing_C_DEFINED
00041
00042 #include "FeatureMatching/GeometricHashing.H"
00043 #include "Image/DrawOps.H"
00044 #include "GUI/DebugWin.H"
00045 #include <fcntl.h>
00046
00047
00048 GeometricHashing::GeometricHashing() :
00049 itsTableWidth(0.10),
00050 itsNumFeatures(0),
00051 itsNumBinEntries(0)
00052 {
00053 itsHashTable = Image<TableEntry>(32,32,ZEROS);
00054 itsTableWidth = 1/32.0;
00055 }
00056
00057
00058 GeometricHashing::~GeometricHashing()
00059 {
00060
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 void GeometricHashing::addModel(const Model& model)
00090 {
00091 itsModels.push_back(model);
00092
00093
00094 Point2D<int> tl = model.v[0];
00095 Point2D<int> br = model.v[0];
00096 for(uint i=0; i<model.v.size(); i++)
00097 {
00098 if (br.i > model.v[i].i)
00099 br.i = model.v[i].i;
00100 if (br.j > model.v[i].j)
00101 br.j = model.v[i].j;
00102
00103 if (tl.i < model.v[i].i)
00104 tl.i = model.v[i].i;
00105 if (tl.j < model.v[i].j)
00106 tl.j = model.v[i].j;
00107 }
00108
00109 std::vector<Point2D<float> > featureLoc = changeBasis(model.v, tl, br);
00110 for(uint i=0; i<featureLoc.size(); i++)
00111 insertToHashTable(featureLoc[i], 0, 0, model.id, model.rot);
00112
00113 }
00114
00115 void GeometricHashing::insertToHashTable(const Point2D<float> loc,
00116 int p1, int p2, int modelId,
00117 Point3D<float> rot)
00118 {
00119
00120 ModelTableEntry mte;
00121 mte.modelId = modelId;
00122 mte.rot = rot;
00123 mte.featureLoc = loc;
00124 mte.basisP1 = p1;
00125 mte.basisP2 = p2;
00126
00127 Image<GeometricHashing::TableEntry>::iterator iter = findInHash(loc);
00128 if (iter != NULL)
00129 iter->modelEntries.push_back(mte);
00130 }
00131
00132
00133 Image<GeometricHashing::TableEntry>::iterator
00134 GeometricHashing::findInHash(const Point2D<float>& loc)
00135 {
00136
00137 int i = (itsHashTable.getWidth()/2) + int( floor(loc.i / itsTableWidth) );
00138 int j = (itsHashTable.getHeight()/2) + int( floor(loc.j / itsTableWidth) );
00139
00140 Image<GeometricHashing::TableEntry>::iterator iter = NULL;
00141
00142 if (itsHashTable.coordsOk(i,j))
00143 {
00144 iter = itsHashTable.beginw();
00145 iter += (i + j*itsHashTable.getWidth());
00146 }
00147 return iter;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 std::vector<GeometricHashing::Acc> GeometricHashing::getVotes(std::vector<Point2D<int> >& input)
00213 {
00214 std::vector<Acc> acc;
00215
00216 if (input.size() <= 0)
00217 return acc;
00218
00219
00220 Point2D<int> tl = input[0];
00221 Point2D<int> br = input[0];
00222 for(uint i=0; i<input.size(); i++)
00223 {
00224 if (br.i > input[i].i)
00225 br.i = input[i].i;
00226 if (br.j > input[i].j)
00227 br.j = input[i].j;
00228
00229 if (tl.i < input[i].i)
00230 tl.i = input[i].i;
00231 if (tl.j < input[i].j)
00232 tl.j = input[i].j;
00233 }
00234
00235 std::vector<Point2D<float> > newInput = changeBasis(input, tl, br);
00236
00237 Point2D<float> center(tl.i+(br.i - tl.i)/2,
00238 tl.j+(br.j - tl.j)/2);
00239
00240
00241
00242 for(uint i=0; i<newInput.size(); i++)
00243 {
00244 Image<GeometricHashing::TableEntry>::iterator iter =
00245 findInHash(newInput[i]);
00246 if (iter != NULL)
00247 {
00248 for(uint j=0; j<iter->modelEntries.size(); j++)
00249 {
00250 ModelTableEntry mte = iter->modelEntries[j];
00251
00252
00253 bool found = false;
00254 for(uint i=0; i<acc.size(); i++)
00255 {
00256 if (acc[i].modelId == mte.modelId &&
00257 acc[i].rot == mte.rot)
00258 {
00259 found = true;
00260 acc[i].votes++;
00261 }
00262 }
00263
00264 if (!found)
00265 {
00266 Acc newAcc;
00267 newAcc.modelId = mte.modelId;
00268 newAcc.rot = mte.rot;
00269 newAcc.votes = 1;
00270 newAcc.center = center;
00271 acc.push_back(newAcc);
00272 }
00273 }
00274 }
00275 }
00276
00277 return acc;
00278 }
00279
00280 Image<PixRGB<byte> > GeometricHashing::getHashTableImage()
00281 {
00282
00283 int binWidth = 10;
00284 Image<PixRGB<byte> > img(itsHashTable.getDims()*binWidth, ZEROS);
00285 drawGrid(img, binWidth, binWidth, 1, 1, PixRGB<byte>(0,0,255));
00286 drawLine(img, Point2D<int>(0, img.getHeight()/2),
00287 Point2D<int>(img.getWidth(), img.getHeight()/2),
00288 PixRGB<byte>(0,0,255),2);
00289 drawLine(img, Point2D<int>(img.getWidth()/2, 0),
00290 Point2D<int>(img.getWidth()/2, img.getHeight()),
00291 PixRGB<byte>(0,0,255),2);
00292
00293 float scale = binWidth/itsTableWidth;
00294 for(uint i=0; i<itsHashTable.size(); i++)
00295 {
00296 TableEntry te = itsHashTable[i];
00297 for(uint j=0; j<te.modelEntries.size(); j++)
00298 {
00299 ModelTableEntry mte = te.modelEntries[j];
00300 int x = (img.getWidth()/2) + (int)(scale*mte.featureLoc.i);
00301 int y = (img.getHeight()/2) - (int)(scale*mte.featureLoc.j);
00302 drawCircle(img, Point2D<int>(x,y), 3, PixRGB<byte>(0,255,0));
00303 }
00304 }
00305
00306 return img;
00307
00308 }
00309
00310
00311 std::vector<Point2D<float> > GeometricHashing::changeBasis(
00312 const std::vector<Point2D<int> >& featureLoc,
00313 int p1, int p2)
00314 {
00315
00316 std::vector<Point2D<float> > newFeatureLoc;
00317
00318 float modelScale = 1/sqrt( squareOf(featureLoc[p2].i - featureLoc[p1].i) +
00319 squareOf(featureLoc[p2].j - featureLoc[p1].j) );
00320
00321 float ang = 0;
00322 if ((featureLoc[p2].i - featureLoc[p1].i) != 0)
00323 ang = -atan((featureLoc[p2].j - featureLoc[p1].j)/(featureLoc[p2].i - featureLoc[p1].i));
00324
00325
00326 for(uint i=0; i<featureLoc.size(); i++)
00327 {
00328 float x = modelScale*(featureLoc[i].i);
00329 float y = modelScale*(featureLoc[i].j);
00330
00331 newFeatureLoc.push_back(
00332 Point2D<float>((x * cos(ang) - y * sin(ang)),
00333 (y * cos(ang) + x * sin(ang))));
00334 }
00335
00336
00337 Point2D<float> center(newFeatureLoc[p1].i+(newFeatureLoc[p2].i - newFeatureLoc[p1].i)/2,
00338 newFeatureLoc[p1].j+(newFeatureLoc[p2].j - newFeatureLoc[p1].j)/2);
00339 for(uint i=0; i<newFeatureLoc.size(); i++)
00340 newFeatureLoc[i] -= center;
00341
00342
00343 return newFeatureLoc;
00344 }
00345
00346 std::vector<Point2D<float> > GeometricHashing::changeBasis(
00347 const std::vector<Point2D<int> >& featureLoc,
00348 Point2D<int> tl,
00349 Point2D<int> br)
00350 {
00351
00352 std::vector<Point2D<float> > newFeatureLoc;
00353
00354
00355 Point2D<float> center(tl.i+(br.i - tl.i)/2,
00356 tl.j+(br.j - tl.j)/2);
00357
00358 float modelScale = 1/sqrt( squareOf(br.i - tl.i) +
00359 squareOf(br.j - tl.j) );
00360
00361
00362 float ang = 0;
00363 for(uint i=0; i<featureLoc.size(); i++)
00364 {
00365 float x = modelScale*(featureLoc[i].i - center.i);
00366 float y = modelScale*(featureLoc[i].j - center.j);
00367
00368 newFeatureLoc.push_back(
00369 Point2D<float>((x * cos(ang) - y * sin(ang)),
00370 (y * cos(ang) + x * sin(ang))));
00371 }
00372
00373 return newFeatureLoc;
00374 }
00375
00376 void GeometricHashing::writeTable(const char* filename)
00377 {
00378 int fd;
00379
00380 if ((fd = creat(filename, 0644)) == -1)
00381 LFATAL("Can not open %s for saving\n", filename);
00382
00383
00384 int ret;
00385 int width = itsHashTable.getWidth();
00386 int height = itsHashTable.getHeight();
00387 ret = write(fd, (char *) &width, sizeof(int));
00388 ret = write(fd, (char *) &height, sizeof(int));
00389
00390
00391 for(int j=0; j<height; j++)
00392 for(int i=0; i<width; i++)
00393 {
00394 GeometricHashing::TableEntry te = itsHashTable.getVal(i,j);
00395
00396 size_t numEntries = te.modelEntries.size();
00397 ret = write(fd, (char *) &numEntries, sizeof(size_t));
00398
00399 for(uint idx=0; idx<numEntries; idx++)
00400 {
00401 ModelTableEntry mte = te.modelEntries[idx];
00402 ret = write(fd, (char *) &mte, sizeof(ModelTableEntry));
00403 }
00404 }
00405 }
00406
00407 void GeometricHashing::readTable(const char* filename)
00408 {
00409 int fd;
00410 if ((fd = open(filename, 0, 0644)) == -1) return;
00411
00412 int ret;
00413 LINFO("Reading from %s", filename);
00414
00415
00416 int width;
00417 int height;
00418 ret = read(fd, (char *) &width, sizeof(int));
00419 ret = read(fd, (char *) &height, sizeof(int));
00420 LINFO("Width %i %i", width, height);
00421
00422 itsHashTable = Image<TableEntry>(width,height,ZEROS);
00423
00424
00425 for(int j=0; j<height; j++)
00426 for(int i=0; i<width; i++)
00427 {
00428
00429 size_t numEntries;
00430 ret = read(fd, (char *) &numEntries, sizeof(size_t));
00431
00432
00433 for(uint idx=0; idx<numEntries; idx++)
00434 {
00435 ModelTableEntry mte;
00436 ret = read(fd, (char *) &mte, sizeof(ModelTableEntry));
00437
00438 Image<GeometricHashing::TableEntry>::iterator iter = NULL;
00439 iter = itsHashTable.beginw();
00440 iter += (i + j*itsHashTable.getWidth());
00441 iter->modelEntries.push_back(mte);
00442 }
00443 }
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 #endif
00453