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
00035 #include <srs_env_model_percp/but_plane_detector/parameter_space_hierarchy.h>
00036
00037 using namespace srs_env_model_percp;
00038 using namespace std;
00039 using namespace sensor_msgs;
00040 using namespace cv;
00041 using namespace but_plane_detector;
00042
00044
00045
00046
00047
00048
00049
00050
00052 ParameterSpaceHierarchy::ParameterSpaceHierarchy(double anglemin, double anglemax, double zmin, double zmax, double angleRes, double shiftRes)
00053 {
00054 m_init = false;
00055 m_angleStep = (anglemax - anglemin) / (angleRes - 1);
00056 m_shiftStep = (zmax - zmin) / (shiftRes - 1);
00057 m_angleLoStep = m_angleStep * DEFAULT_BIN_SIZE;
00058 m_shiftLoStep = m_shiftStep * DEFAULT_BIN_SIZE;
00059
00060 m_angleSize = (anglemax - anglemin) / m_angleStep + 1;
00061 m_angleSize2 = m_angleSize * m_angleSize;
00062 m_shiftSize = (zmax - zmin) / m_shiftStep + 1;
00063
00064 assert(m_angleSize % DEFAULT_BIN_SIZE == 0 && m_shiftSize % DEFAULT_BIN_SIZE == 0);
00065
00066 m_angleLoSize = m_angleSize / DEFAULT_BIN_SIZE;
00067 m_angleLoSize2 = m_angleSize2 / (DEFAULT_BIN_SIZE*DEFAULT_BIN_SIZE);
00068 m_shiftLoSize = m_shiftSize / DEFAULT_BIN_SIZE;
00069
00070 m_shiftmin = zmin;
00071 m_shiftmax = zmax;
00072 m_anglemin = anglemin;
00073 m_anglemax = anglemax;
00074
00075 m_size = m_angleSize2 * m_shiftSize;
00076 m_loSize = m_angleLoSize2 * m_shiftLoSize;
00077
00078 m_hiSize = DEFAULT_BIN_SIZE*DEFAULT_BIN_SIZE*DEFAULT_BIN_SIZE;
00079 m_hiSize2 = DEFAULT_BIN_SIZE*DEFAULT_BIN_SIZE;
00080 m_dataLowRes = (double **)malloc(sizeof(double*)*m_loSize);
00081 for (int i = 0; i < m_loSize; ++i)
00082 m_dataLowRes[i] = NULL;
00083 }
00084
00086
00088 ParameterSpaceHierarchy::~ParameterSpaceHierarchy()
00089 {
00090 for (int i = 0; i < m_loSize; ++i)
00091 if (m_dataLowRes[i] != NULL) free(m_dataLowRes[i]);
00092
00093 free(m_dataLowRes);
00094 }
00095
00096 void ParameterSpaceHierarchy::clear()
00097 {
00098 for (int i = 0; i < m_loSize; ++i)
00099 {
00100 if (m_dataLowRes[i] != NULL) free(m_dataLowRes[i]);
00101 m_dataLowRes[i] = NULL;
00102 }
00103
00104 }
00105
00107
00108
00109
00110
00111
00112
00114 void ParameterSpaceHierarchy::toAngles(float x, float y, float z, float &a1, float &a2)
00115 {
00116 a1 = atan2(z, x);
00117
00118 x = z * sin(a1) + x * cos(a1);
00119 a2 = atan2(y, x);
00120 }
00121
00123
00124
00125
00126
00127
00128
00130 void ParameterSpaceHierarchy::toEuklid(float a1, float a2, float &x, float &y, float &z)
00131 {
00132 float auxx = cos(-a2);
00133 y = -sin(-a2);
00134 x = auxx * cos(-a1);
00135 z = -auxx * sin(-a1);
00136 }
00137
00139
00140
00141
00142
00144 double ParameterSpaceHierarchy::get(int angle1, int angle2, int z)
00145 {
00146 IndexStruct index = getIndex(angle1, angle2, z);
00147
00148
00149
00150 if (m_dataLowRes[index.lowResolutionIndex] == NULL)
00151 return 0.0;
00152 else
00153 return m_dataLowRes[index.lowResolutionIndex][index.highResolutionIndex];
00154
00155 }
00156
00158
00159
00160
00161
00162
00164 void ParameterSpaceHierarchy::set(int angle1, int angle2, int z, double val)
00165 {
00166 IndexStruct index = getIndex(angle1, angle2, z);
00167 if (m_dataLowRes[index.lowResolutionIndex] == NULL)
00168 {
00169 m_dataLowRes[index.lowResolutionIndex] = (double *)malloc(sizeof(double) *m_hiSize);
00170 memset(m_dataLowRes[index.lowResolutionIndex], 0, m_hiSize * sizeof(double));
00171 }
00172 m_dataLowRes[index.lowResolutionIndex][index.highResolutionIndex] = val;
00173 }
00174
00176
00177
00179 double ParameterSpaceHierarchy::get(int bin_index, int inside_index)
00180 {
00181 if (m_dataLowRes[bin_index] == NULL)
00182 return 0.0;
00183 else
00184 return m_dataLowRes[bin_index][inside_index];
00185 }
00186
00188
00189
00190
00192 void ParameterSpaceHierarchy::set(int bin_index, int inside_index, double val)
00193 {
00194 if (m_dataLowRes[bin_index] == NULL)
00195 {
00196 m_dataLowRes[bin_index] = (double *)malloc(sizeof(double) *m_hiSize);
00197 memset(m_dataLowRes[bin_index], 0, m_hiSize * sizeof(double));
00198 }
00199 m_dataLowRes[bin_index][inside_index] = val;
00200 }
00201
00203
00204
00205
00206
00208 IndexStruct ParameterSpaceHierarchy::getIndex(double angle1, double angle2, double z)
00209 {
00210 IndexStruct index;
00211 int a1 = (angle1-m_anglemin) / m_angleStep;
00212 int a2 = (angle2-m_anglemin) / m_angleStep;
00213 int zz = (z-m_shiftmin) / m_shiftStep;
00214 index.highResolutionIndex = zz%DEFAULT_BIN_SIZE * m_hiSize2 + a2%DEFAULT_BIN_SIZE * DEFAULT_BIN_SIZE + a1%DEFAULT_BIN_SIZE;
00215 index.lowResolutionIndex = zz/DEFAULT_BIN_SIZE * m_angleLoSize2 + a2/DEFAULT_BIN_SIZE * m_angleLoSize + a1/DEFAULT_BIN_SIZE;
00216
00217 return index;
00218 }
00219
00221
00222
00223
00224
00225
00227 void ParameterSpaceHierarchy::fromIndex(int bin_index, int inside_index, int& angle1, int& angle2, int& z)
00228 {
00229
00230
00231 int loZ, loA1, loA2;
00232
00233 z = (bin_index / (m_angleLoSize2));
00234 loZ = inside_index / (m_hiSize2);
00235
00236 angle2 = ((bin_index - z * m_angleLoSize2) / m_angleLoSize);
00237 loA2 = (inside_index - loZ * m_hiSize2) / DEFAULT_BIN_SIZE;
00238
00239 angle1 = (bin_index - (z * m_angleLoSize2) - angle2 * m_angleLoSize);
00240 loA1 = inside_index - (loZ * m_hiSize2) - loA2 * DEFAULT_BIN_SIZE;
00241
00242 z = z*DEFAULT_BIN_SIZE + loZ;
00243 angle2 = angle2*DEFAULT_BIN_SIZE + loA2;
00244 angle1 = angle1*DEFAULT_BIN_SIZE + loA1;
00245 }
00246
00248
00249
00250
00251
00253 IndexStruct ParameterSpaceHierarchy::getIndex(int angle1, int angle2, int z)
00254 {
00255 IndexStruct index;
00256
00257 index.highResolutionIndex = z%DEFAULT_BIN_SIZE * m_hiSize2 + angle2%DEFAULT_BIN_SIZE * DEFAULT_BIN_SIZE + angle1%DEFAULT_BIN_SIZE;
00258 index.lowResolutionIndex = z/DEFAULT_BIN_SIZE * m_angleLoSize2 + angle2/DEFAULT_BIN_SIZE * m_angleLoSize + angle1/DEFAULT_BIN_SIZE;
00259
00260 return index;
00261 }
00262
00264
00265
00266
00267
00268
00269
00270
00272 void ParameterSpaceHierarchy::getIndex(double angle1, double angle2, double z, int &angle1Index, int &angle2Index, int &shiftIndex)
00273 {
00274 angle1Index = (angle1-m_anglemin) / m_angleStep;
00275 angle2Index = (angle2-m_anglemin) / m_angleStep;
00276 shiftIndex = (z-m_shiftmin) / m_shiftStep;
00277 }
00278
00280
00281
00282
00283
00284
00286 void ParameterSpaceHierarchy::addVolume(ParameterSpace &second, int angle1, int angle2, int shift)
00287 {
00288
00289 double secondAngleHalf = second.m_angleSize / 2;
00290 double secondShiftHalf = second.m_shiftSize / 2;
00291 int shiftThis, angle1This, angle2This;
00292 int shiftS, angle1S, angle2S;
00293
00294 for (shiftS = 0, shiftThis = shift - secondShiftHalf; shiftS < second.m_shiftSize; ++shiftS, ++shiftThis)
00295 for (angle2S=0, angle2This = angle2 - secondAngleHalf; angle2S < second.m_angleSize; ++angle2S, ++angle2This)
00296 for (angle1S=0, angle1This = angle1 - secondAngleHalf; angle1S < second.m_angleSize; ++angle1S, ++angle1This)
00297 {
00298 if (angle1This >= 0 && angle1This < m_angleSize &&
00299 angle2This >= 0 && angle2This < m_angleSize &&
00300 shiftThis >= 0 && shiftThis < m_shiftSize)
00301 {
00302 set(angle1This, angle2This, shiftThis, get(angle1This, angle2This, shiftThis) + second(angle1S, angle2S, shiftS));
00303 }
00304
00305 }
00306 }
00307
00309
00310
00311
00312
00313
00314
00316 void ParameterSpaceHierarchy::addVolume(ParameterSpace &second, int angle1, int angle2, int shift, float factor)
00317 {
00318 double secondAngleHalf = second.m_angleSize / 2;
00319 double secondShiftHalf = second.m_shiftSize / 2;
00320 int shiftThis, angle1This, angle2This;
00321 int shiftS, angle1S, angle2S;
00322
00323 for (shiftS = 0, shiftThis = shift - secondShiftHalf; shiftS < second.m_shiftSize; ++shiftS, ++shiftThis)
00324 for (angle2S=0, angle2This = angle2 - secondAngleHalf; angle2S < second.m_angleSize; ++angle2S, ++angle2This)
00325 for (angle1S=0, angle1This = angle1 - secondAngleHalf; angle1S < second.m_angleSize; ++angle1S, ++angle1This)
00326 {
00327 if (angle1This >= 0 && angle1This < m_angleSize &&
00328 angle2This >= 0 && angle2This < m_angleSize &&
00329 shiftThis >= 0 && shiftThis < m_shiftSize)
00330 {
00331 set(angle1This, angle2This, shiftThis, get(angle1This, angle2This, shiftThis) + factor * second(angle1S, angle2S, shiftS));
00332 }
00333
00334 }
00335 }
00336
00338
00339
00340
00342 int ParameterSpaceHierarchy::findMaxima(tPlanes &indices, double min_value, int neighborhood, int around)
00343 {
00344 float a, b, c;
00345 int maxind = -1;
00346 float max = -1;
00347 int angle1, angle2, shift;
00348
00349 int around3 = around + around + 1;
00350 around3 = around3 * around3 * around3;
00351 ParameterSpaceHierarchyFullIterator it(this);
00352
00353
00354 while (not it.end)
00355 {
00356 double val = it.getVal();
00357
00358 if (val > min_value)
00359 {
00360 this->fromIndex(it.bin_index, it.inside_index, angle1, angle2, shift);
00361
00362
00363 if (angle1 >= neighborhood+around && angle1 < m_angleSize-(neighborhood+around) &&
00364 angle2 >= neighborhood+around && angle2 < m_angleSize-(neighborhood+around) &&
00365 shift >= neighborhood+around && shift < m_shiftSize-(neighborhood+around))
00366 {
00367 val = 0.0;
00368
00369 for (int a1 = -neighborhood; a1 <= neighborhood; ++a1)
00370 for (int a2 = -neighborhood; a2 <= neighborhood; ++a2)
00371 for (int s = -neighborhood; s <= neighborhood; ++s)
00372 val += get(angle1+a1, angle2+a2, shift+s);
00373
00374
00375 bool ok = true;
00376 double aux;
00377 int xx, yy, zz;
00378
00379
00380 for (int x = -around; x <= around; ++x)
00381 for (int y = -around; y <= around; ++y)
00382 for (int z = -around; z <= around; ++z)
00383 {
00384 xx = angle1 + x;
00385 yy = angle2 + y;
00386 zz = shift + z;
00387 aux = 0.0;
00388 for (int a1 = -neighborhood; a1 <= neighborhood; ++a1)
00389 for (int a2 = -neighborhood; a2 <= neighborhood; ++a2)
00390 for (int s = -neighborhood; s <= neighborhood; ++s)
00391 aux += get(xx+a1, yy+a2, zz+s);
00392 if (val < aux)
00393 {
00394 ok = false;
00395 break;
00396 }
00397 }
00398
00399
00400 if (ok)
00401 {
00402
00403
00404
00405
00406
00407
00408
00409
00410 double aroundx = 0;
00411 double aroundy = 0;
00412 double aroundz = 0;
00413 double arounds = 0;
00414 for (int x = -around; x <= around; ++x)
00415 for (int y = -around; y <= around; ++y)
00416 for (int z = -around; z <= around; ++z)
00417 {
00418 xx = angle1 + x;
00419 yy = angle2 + y;
00420 zz = shift + z;
00421 toEuklid(getAngle(xx), getAngle(yy), a, b, c);
00422 aroundx += a;
00423 aroundy += b;
00424 aroundz += c;
00425 arounds += getShift(zz);
00426 }
00427
00428 aroundx /= around3;
00429 aroundy /= around3;
00430 aroundz /= around3;
00431 arounds /= around3;
00432
00433 indices.push_back(Plane<float>(aroundx, aroundy, aroundz, arounds));
00434 if (val > max)
00435 {
00436 max = val;
00437 maxind = indices.size() - 1;
00438 }
00439 }
00440 }
00441 }
00442 ++it;
00443 }
00444 return maxind;
00445
00446 }
00447
00449
00450
00452 double ParameterSpaceHierarchy::getAngle(int index)
00453 {
00454 return (m_angleStep * ((double)index)) + m_anglemin;
00455 }
00456
00458
00459
00461 double ParameterSpaceHierarchy::getShift(int index)
00462 {
00463 return ((double)index) * m_shiftStep + m_shiftmin;
00464 }
00465
00467
00469 int ParameterSpaceHierarchy::getSize()
00470 {
00471 int size = 0;
00472 for (int i = 0; i < m_loSize; ++i)
00473 if (m_dataLowRes[i] != NULL) size += m_hiSize;
00474 return size;
00475 }
00476
00478
00479
00480
00481
00483 double ParameterSpaceHierarchy::get(double angle1, double angle2, double z)
00484 {
00485 IndexStruct index = getIndex(angle1, angle2, z);
00486
00487 if (m_dataLowRes[index.lowResolutionIndex] == NULL)
00488 return 0.0;
00489 else
00490 return m_dataLowRes[index.lowResolutionIndex][index.highResolutionIndex];
00491 }
00492
00494
00495
00496
00497
00498
00500 void ParameterSpaceHierarchy::set(double angle1, double angle2, double z, double val)
00501 {
00502 IndexStruct index = getIndex(angle1, angle2, z);
00503
00504 if (m_dataLowRes[index.lowResolutionIndex] == NULL)
00505 {
00506 m_dataLowRes[index.lowResolutionIndex] = (double *)malloc(sizeof(double) *m_hiSize);
00507 memset(m_dataLowRes[index.lowResolutionIndex], 0, m_hiSize * sizeof(double));
00508 }
00509 m_dataLowRes[index.lowResolutionIndex][index.highResolutionIndex] = val;
00510 }
00511
00512