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 #include "Beobot/ImageSpring.H"
00040
00041 #include "Channels/Jet.H"
00042 #include "Image/ColorOps.H"
00043 #include "Image/DrawOps.H"
00044 #include "Image/FilterOps.H"
00045 #include "Image/IO.H"
00046 #include "Image/Image.H"
00047 #include "Image/MathOps.H"
00048 #include "Image/Pixels.H"
00049 #include "Image/ShapeOps.H"
00050 #include "Image/Transforms.H"
00051 #include "Util/Assert.H"
00052 #include "Util/MathFunctions.H"
00053
00054
00055
00056 template<class T>
00057 void ImageSpring<T>::getStats()
00058 {
00059 ASSERT(this->initialized());
00060
00061
00062
00063 mean = this->getVal(0); mean *= 0.0f; weight = mean;
00064 stdev = mean; T mom2(mean);
00065
00066 for (int n = 0; n < nbHeuristic; n++)
00067 {
00068 T randomPixel = this->getVal(randomUpToNotIncluding(this->getSize()));
00069 mean += randomPixel;
00070 inplaceSquare(randomPixel);
00071 mom2 += randomPixel;
00072 }
00073 mean /= (float)nbHeuristic;
00074 mom2 /= (float)nbHeuristic;
00075 T mean2(mean); inplaceSquare(mean2);
00076
00077
00078
00079 stdev = mom2;
00080 stdev -= mean2;
00081 inplaceRectify(stdev);
00082 stdev = sqrt(stdev);
00083 weight = inverse(stdev, 1.0f);
00084 }
00085
00086
00087 template<class T>
00088 void ImageSpring<T>::getStatsDist()
00089 {
00090 ASSERT(this->initialized());
00091 meanDist = 0.0; double mom2 = 0.0;
00092
00093 for (int n = 0; n < nbHeuristic; n++)
00094 {
00095 int randomIndex = randomUpToNotIncluding(this->getSize());
00096 T randomPixel = this->getVal(randomIndex);
00097
00098 bool neighborDefined = false; int neighborNumber, neighborIndex;
00099 int attempt = 0;
00100 while (! neighborDefined && attempt++ < 10)
00101 {
00102 neighborNumber = randomUpToNotIncluding(nbNeighbors) + 1;
00103 neighborDefined =
00104 getNeighbor(randomIndex, neighborNumber, neighborIndex);
00105 }
00106 if (neighborDefined) {
00107 T randomNeighbor = this->getVal(neighborIndex);
00108 double d = distance(randomPixel, randomNeighbor, weight);
00109 meanDist += d; mom2 += squareOf(d);
00110 } else n --;
00111 }
00112 meanDist /= (double)nbHeuristic;
00113 mom2 /= (double)nbHeuristic;
00114
00115
00116 stdevDist = sqrt(mom2 - squareOf(meanDist));
00117 }
00118
00119
00120 template<class T>
00121 void ImageSpring<T>::initClustering(bool initPosMasses)
00122 {
00123
00124 if (initPosMasses)
00125 {
00126 for (int x = 0; x < this->getWidth(); x++)
00127 for (int y = 0; y < this->getHeight(); y++)
00128 setPos(Point2D<int>(x, y), float(x), float(y));
00129 memcpy(oldPosX, posX, this->getSize() * sizeof(float));
00130 memcpy(oldPosY, posY, this->getSize() * sizeof(float));
00131 }
00132
00133
00134 getStats(); getStatsDist(); computeStiff();
00135 }
00136
00137
00138 template<class T>
00139 void ImageSpring<T>::computeStiff(void)
00140 {
00141 for (int currentIndex = 0; currentIndex < this->getSize(); currentIndex++)
00142 {
00143 Point2D<int> currentPoint;
00144 getXY(currentIndex, currentPoint);
00145
00146
00147
00148 setStiff(currentPoint, 0, 0.5f);
00149
00150 T currval = this->getVal(currentIndex);
00151
00152 for (int n = 1; n <= nbNeighbors; n++)
00153 {
00154 int neighborIndex;
00155 if (getNeighbor(currentIndex, n, neighborIndex))
00156 {
00157 float alikeness = distance(currval,this->getVal(neighborIndex),weight);
00158
00159
00160
00161 alikeness = -2.0f * (alikeness - meanDist) / stdevDist;
00162
00163 if (alikeness > 0.0f) setStiff(currentPoint, n, alikeness);
00164 else setStiff(currentPoint, n, 0.0);
00165 }
00166 }
00167 }
00168 }
00169
00170
00171 template<class T>
00172 void ImageSpring<T>::computePos( const float dt )
00173 {
00174 float *newPosX = new float[this->getSize()];
00175 float *newPosY = new float[this->getSize()];
00176
00177 for (int x = 0; x < this->getWidth(); x++)
00178 for (int y = 0; y < this->getHeight(); y++)
00179 {
00180 int ci; getIndex(Point2D<int>(x, y), ci);
00181
00182
00183 float X = posX[ci], Y = posY[ci];
00184
00185
00186 float fx = stiff[ci][0] * (float(x) - X);
00187 float fy = stiff[ci][0] * (float(y) - Y);
00188
00189 for (int n = 1; n <= nbNeighbors; n++)
00190 {
00191 int neighborIndex;
00192 if (getNeighbor(ci, n, neighborIndex))
00193 {
00194
00195 float stif = stiff[ci][n];
00196
00197
00198 fx += stif * (posX[neighborIndex] - X);
00199 fy += stif * (posY[neighborIndex] - Y);
00200 }
00201 }
00202
00203
00204 const float gamma = 1.0f;
00205
00206
00207 newPosX[ci] = 2.0f * posX[ci] - oldPosX[ci] + dt * dt * fx
00208 - dt * gamma * (posX[ci] - oldPosX[ci]);
00209 newPosY[ci] = 2.0f * posY[ci] - oldPosY[ci] + dt * dt * fy
00210 - dt * gamma * (posY[ci] - oldPosY[ci]);
00211 }
00212
00213
00214 delete [] oldPosX; delete [] oldPosY; oldPosX = posX; oldPosY = posY;
00215 posX = newPosX; posY = newPosY;
00216 }
00217
00218
00219 template<class T>
00220 float ImageSpring<T>::getDistanceMasses(const int idx1, const int idx2) const
00221 { return sqrt(squareOf(posX[idx1]-posX[idx2]) + squareOf(posY[idx1]-posY[idx2])); }
00222
00223
00224 template <class T>
00225 void ImageSpring<T>::getPositions(Image< PixRGB<byte> >& img, const int zoom)
00226 {
00227 img.resize(this->getWidth() * zoom, this->getHeight() * zoom, true);
00228 float maxstiff = 0.0;
00229
00230
00231 for (int i = 0; i < this->getSize(); i ++)
00232 {
00233 Point2D<int> pp(int(zoom * (posX[i] + 0.5)), int(zoom * (posY[i] + 0.5)));
00234 int ni;
00235
00236 for (int n = 1; n <= nbNeighbors; n ++)
00237 if (getNeighbor(i, n, ni))
00238 {
00239 Point2D<int> np(int(zoom * (posX[ni]+0.5)), int(zoom * (posY[ni]+0.5)));
00240 drawLine(img, pp, np,
00241 PixRGB<byte>(150.0f + 50.0f * stiff[i][n],
00242 100.0f * stiff[i][n],
00243 0));
00244 if (stiff[i][n] > maxstiff) maxstiff = stiff[i][n];
00245 }
00246 }
00247
00248
00249
00250 PixRGB<byte> blue(0, 0, 255);
00251 for (int i = 0; i < this->getSize(); i ++)
00252 {
00253 Point2D<int> pp(int(zoom * (posX[i] + 0.5)), int(zoom * (posY[i] + 0.5)));
00254 drawDisk(img, pp, 2, blue);
00255 }
00256 }
00257
00258
00259 template <class T>
00260 void ImageSpring<T>::goGraph(Image<int32> &marked, const int currentIndex,
00261 const int32 color, const int begin)
00262 {
00263
00264 int nbNeighborsSameColor = 0, neighborIndex;
00265 for (int n = 1; n <= nbNeighbors; n ++)
00266 if (getNeighbor(currentIndex, n, neighborIndex) &&
00267 marked.getVal(neighborIndex) == color)
00268 nbNeighborsSameColor ++;
00269
00270
00271
00272 if (begin <= 0 && nbNeighborsSameColor < 5) return;
00273
00274
00275 marked.setVal(currentIndex, color);
00276
00277
00278
00279
00280 for (int n = 1; n <= nbNeighbors; n ++)
00281 if (getNeighbor(currentIndex, n, neighborIndex) &&
00282 marked.getVal(neighborIndex) == 0 &&
00283 getDistanceMasses(currentIndex, neighborIndex) < 1.0)
00284 goGraph(marked, neighborIndex, color, begin - 1);
00285 }
00286
00287
00288 template <class T>
00289 void ImageSpring<T>::getClusteredImage(const Image< PixRGB<byte> > &scene,
00290 Image< PixRGB<byte> > &clusteredImage,
00291 Point2D<int> &supposedTrackCentroid,
00292 const Point2D<int>& previousTrackCentroid)
00293 {
00294 int preferedMeanX = 0, preferedMeanY = 0;
00295
00296 Image<int32> marked(this->getDims(), ZEROS);
00297 Image< PixRGB<byte> > clustered(scene.getDims(), NO_INIT);
00298
00299 int pX = scene.getWidth() / this->getWidth();
00300 int pY = scene.getHeight() / this->getHeight();
00301
00302 PixRGB<byte> whitePixel(255, 255, 255);
00303
00304 float highestScore = std::numeric_limits<float>::max();
00305
00306
00307
00308
00309 int32 color = 0;
00310
00311 for (int x = 0; x < this->getWidth(); x++ )
00312 for (int y = 0; y < this->getHeight(); y++ )
00313 {
00314 color ++;
00315
00316 int meanX = 0, meanY = 0;
00317
00318 if (marked.getVal(x, y) == 0)
00319 {
00320
00321 goGraph(marked, x + this->getWidth() * y, color);
00322
00323 PixRGB<int32> meanPixel(0, 0, 0);
00324 PixRGB<byte> tmpPixel;
00325 int nbPixels = 0;
00326
00327
00328 for (int xp = 0; xp < this->getWidth(); xp ++ )
00329 for (int yp = 0; yp < this->getHeight(); yp ++)
00330 if (marked.getVal(xp, yp) == color)
00331 for (int dx = 0; dx < pX; dx ++)
00332 for (int dy = 0; dy < pY; dy ++)
00333 {
00334 scene.getVal(xp * pX + dx, yp * pY + dy, tmpPixel);
00335 meanPixel += tmpPixel;
00336 meanX += xp * pX + dx;
00337 meanY += yp * pY + dy;
00338 nbPixels ++;
00339 }
00340 meanPixel /= nbPixels; meanX /= nbPixels; meanY /= nbPixels;
00341
00342
00343 bool ignoreGroup;
00344 if (nbPixels < scene.getWidth() * scene.getHeight() / 30)
00345 { meanPixel.set(0, 0, 0); ignoreGroup = true; }
00346 else
00347 ignoreGroup=false;
00348
00349
00350
00351 for (int xp = 0; xp < this->getWidth(); xp ++)
00352 for (int yp = 0; yp < this->getHeight(); yp ++)
00353 if (marked.getVal(xp, yp) == color)
00354 for (int dx = 0; dx < pX; dx ++)
00355 for (int dy = 0; dy < pY; dy++)
00356 clustered.setVal(xp * pX + dx, yp * pY + dy, meanPixel);
00357
00358
00359 if (!ignoreGroup)
00360 drawCross(clustered, Point2D<int>(meanX, meanY), whitePixel);
00361
00362 #define LIKE_CENTER 1.0
00363 #define LIKE_PREVIOUS 1.0
00364 #define LIKE_BIG 1.0
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 float currentScore =
00382 LIKE_CENTER *
00383 sqrt( double( (float)squareOf(meanX - clustered.getWidth()/2) +
00384 (float)squareOf(meanY - clustered.getHeight()) ) )
00385 / (float)clustered.getHeight()
00386 + LIKE_PREVIOUS *
00387 sqrt( double( squareOf(meanX - previousTrackCentroid.i) +
00388 squareOf(meanY - previousTrackCentroid.j) ) )
00389 / (float)clustered.getHeight()
00390 - LIKE_BIG * ( (float)nbPixels / ((float)clustered.getHeight()*
00391 (float)clustered.getWidth()));
00392
00393
00394
00395 if ((currentScore < highestScore) && (!ignoreGroup))
00396
00397 {
00398 preferedMeanX = meanX; preferedMeanY = meanY;
00399 highestScore = currentScore;
00400 }
00401
00402 }
00403 }
00404
00405
00406 int xp = clustered.getWidth() / 2;
00407 for(int yp = 0; yp < clustered.getHeight(); yp ++)
00408 if (yp % 3 == 0) clustered.setVal(xp, yp, whitePixel);
00409
00410
00411 drawCross(clustered, Point2D<int>(preferedMeanX, preferedMeanY), whitePixel, 5, 2);
00412
00413
00414 clusteredImage = clustered;
00415 supposedTrackCentroid.i = preferedMeanX;
00416 supposedTrackCentroid.j = preferedMeanY;
00417 }
00418
00419
00420
00421 template class ImageSpring< Jet<float> >;
00422
00423
00424
00425
00426
00427