RSMarkovCluster.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. #include "RSMarkovCluster.h"
  2. /*
  3. Alle Koordinatenangaben orientieren sich an der Matrixschreibweise, dh. (y,x)
  4. Zeile y und Spalte x. Gespeichert werden Koordianten (soweit nicht anders angegeben)
  5. im typedef Coord. Dieses baut auf std::pair<int,int> auf. Damit ist coord.first die
  6. Zeile und coord.second die Spalte.
  7. */
  8. using namespace OBJREC;
  9. using namespace NICE;
  10. using namespace std;
  11. #define DEBUGMODE
  12. #ifdef DEBUGMODE
  13. #include <boost/date_time/posix_time/posix_time.hpp>
  14. using namespace boost::posix_time;
  15. #endif
  16. RSMarkovCluster::RSMarkovCluster ( const Config* conf )
  17. {
  18. const string section = "MarkovCluster";
  19. // Parameter aus der Konfigurationsdatei auslesen
  20. r = conf->gD ( section, "clusterradius", 4.5 );
  21. mu = conf->gD ( section, "edgeweight_parameter", 10.0 );
  22. p = conf->gD ( section, "inflation_parameter", 1.4 );
  23. chaosThreshold = conf->gD ( section, "chaos_threshold", 0.001 );
  24. iterations = conf->gI ( section, "iterations", 23 );
  25. }
  26. /*
  27. offsets = {(y,x) | norm((y,x),2)<=r}
  28. Menge aller moeglichen Offsets, dh. offsets enthaelt alle Koordinatenverschiebungen,
  29. welche vom Ursprung (0,0) gesehen kleiner als der gegebene compact-pruning-Parameter
  30. ist. Dadurch wird die Nachbarschaft definiert und die Groesse der Cluster begrenzt.
  31. */
  32. void
  33. RSMarkovCluster::precalcOffsets ( RSMarkovCluster::Offsets& offsets ) const
  34. {
  35. // Fuege in die Offsets alle Pixel der 8er Nachbarschaft und sich selber ein.
  36. offsets.push_back ( Coord ( 0, 0 ) );
  37. offsets.push_back ( Coord ( -1, -1 ) );
  38. offsets.push_back ( Coord ( -1, 0 ) );
  39. offsets.push_back ( Coord ( -1, 1 ) );
  40. offsets.push_back ( Coord ( 0, -1 ) );
  41. offsets.push_back ( Coord ( 0, 1 ) );
  42. offsets.push_back ( Coord ( 1, -1 ) );
  43. offsets.push_back ( Coord ( 1, 0 ) );
  44. offsets.push_back ( Coord ( 1, 1 ) );
  45. int bound = round ( this->r );
  46. for ( int m = -bound; m <= bound; m++ )
  47. {
  48. for ( int n = -bound; n <= bound; n++ )
  49. {
  50. Coord newCoord ( m, n );
  51. if ( ( newCoord.pnorm ( 2 ) <= ( this->r ) )
  52. && ! ( ( m == -1 ) && ( n == -1 ) )
  53. && ! ( ( m == -1 ) && ( n == 0 ) )
  54. && ! ( ( m == -1 ) && ( n == 1 ) )
  55. && ! ( ( m == 0 ) && ( n == -1 ) )
  56. && ! ( ( m == 0 ) && ( n == 0 ) )
  57. && ! ( ( m == 0 ) && ( n == 1 ) )
  58. && ! ( ( m == 1 ) && ( n == -1 ) )
  59. && ! ( ( m == 1 ) && ( n == 0 ) )
  60. && ! ( ( m == 1 ) && ( n == 1 ) ) )
  61. {
  62. offsets.push_back ( newCoord );
  63. }
  64. }
  65. }
  66. }
  67. /*
  68. detours[e] = {(i,j) | offsets(i)+offsets(j)=offsets(e)}
  69. Menger aller moeglichen 2er Pfade von einem gegebenen Pixel zum offset[e].
  70. */
  71. void
  72. RSMarkovCluster::precalcDetours ( RSMarkovCluster::Detours& detours, const RSMarkovCluster::Offsets& offsets ) const
  73. {
  74. // Anzahl der offsets (Nachbarn)
  75. const uint N_e = offsets.size();
  76. // Groesse von Detours anpassen
  77. detours.resize ( N_e );
  78. // diese Tour muss fuer alle Nachbarn berechnet werden
  79. for ( uint e = 0; e < N_e; e++ )
  80. {
  81. // Touren fuer den Offset e
  82. vector< pair< uint, uint > > detours_e;
  83. for ( uint i = 0; i < N_e; i++ )
  84. {
  85. for ( uint j = 0; j < N_e; j++ )
  86. {
  87. if ( ( offsets[i].first + offsets[j].first == offsets[e].first ) && ( offsets[i].second + offsets[j].second == offsets[e].second ) )
  88. {
  89. detours_e.push_back ( pair< uint, uint> ( i, j ) );
  90. }
  91. }
  92. }
  93. detours[e] = detours_e;
  94. }
  95. }
  96. int
  97. RSMarkovCluster::segRegions ( const Image& img, Matrix& mask ) const
  98. {
  99. RSMarkovCluster::Offsets offsets;
  100. RSMarkovCluster::Detours detours;
  101. // Vorausberechnungen der fuer das Clustering erforderlichen Offsets und Detours.
  102. precalcOffsets ( offsets );
  103. const uint n_e = offsets.size();
  104. precalcDetours ( detours, offsets );
  105. // Bilddaten
  106. const uchar* imageData = img.getPixelPointerXY ( 0, 0 );
  107. const uint imageHeight = img.height();
  108. const uint imageWidth = img.width();
  109. const uint channelCount = img.channels();
  110. // MarkovMatrix
  111. NodeCentricRepMatrix L ( imageHeight, imageWidth, n_e );
  112. // Initialisierung der MarkovMatrix.
  113. initMarkovMatrix ( imageData, imageHeight, imageWidth, channelCount, offsets, L );
  114. #ifdef DEBUGMODE
  115. // Anfangszeitpunkt
  116. ptime start ( microsec_clock::local_time() ); //
  117. #endif
  118. // Start des MarkovClustering Prozesses
  119. runClustering ( offsets, detours, L );
  120. #ifdef DEBUGMODE
  121. // Endzeitpunkt
  122. ptime end ( microsec_clock::local_time() ); //
  123. printf ( "[log] Laufzeit Clustering: %ld.%3ldsek\n", ( end - start ).total_milliseconds() / 1000, ( end - start ).total_milliseconds() % 1000 );
  124. #endif
  125. // Finde die Cluster innerhalb der Matrix
  126. const uint clusterCount = findCluster ( offsets, L, mask );
  127. return clusterCount;
  128. }
  129. int
  130. RSMarkovCluster::segRegions ( const ColorImage &cimg, Matrix &mask ) const
  131. {
  132. RSMarkovCluster::Offsets offsets;
  133. RSMarkovCluster::Detours detours;
  134. // Vorausberechnungen der fuer das Clustering erforderlichen Offsets und Detours.
  135. precalcOffsets ( offsets );
  136. const uint n_e = offsets.size();
  137. precalcDetours ( detours, offsets );
  138. // Bilddaten
  139. const uchar* imageData = cimg.getPixelPointerXY ( 0, 0 );
  140. const uint imageHeight = cimg.height();
  141. const uint imageWidth = cimg.width();
  142. const uint channelCount = cimg.channels();
  143. // MarkovMatrix
  144. NodeCentricRepMatrix L ( imageHeight, imageWidth, n_e );
  145. // Initialisierung der MarkovMatrix.
  146. initMarkovMatrix ( imageData, imageHeight, imageWidth, channelCount, offsets, L );
  147. #ifdef DEBUGMODE
  148. // Anfangszeitpunkt
  149. ptime start ( microsec_clock::local_time() ); //
  150. #endif
  151. // Start des MarkovClustering Prozesses
  152. runClustering ( offsets, detours, L );
  153. #ifdef DEBUGMODE
  154. // Endzeitpunkt
  155. ptime end ( microsec_clock::local_time() ); //
  156. printf ( "[log] Laufzeit Clustering: %ld.%3ldsek\n", ( end - start ).total_milliseconds() / 1000, ( end - start ).total_milliseconds() % 1000 );
  157. #endif
  158. // Finde die Cluster innerhalb der Matrix
  159. const uint clusterCount = findCluster ( offsets, L, mask );
  160. return clusterCount;
  161. }
  162. int
  163. RSMarkovCluster::findCluster ( const RSMarkovCluster::Offsets & offsets, NodeCentricRepMatrix& L, Matrix& mask ) const
  164. {
  165. // Bild zum Anzeigen der Attracktoren
  166. Matrix att ( L.getM(), L.getN(), 0.0 );
  167. // L' Matrix: dort werden die Veraenderungen der L-Matrix gespeichert.
  168. NodeCentricRepMatrix M ( L.getM(), L.getN(), L.getE() );
  169. Image attImage ( L.getN(), L.getM() );
  170. for ( uint y = 0;y < L.getM();y++ )
  171. {
  172. for ( uint x = 0;x < L.getN();x++ )
  173. {
  174. attImage.setPixel ( x, y, 0 );
  175. }
  176. }
  177. printf ( "schwache Kanten entfernen\n" );
  178. // Delta um den Kantenschwellwert zu berechnen. Dieser wird von der Summe der abgehenden Kanten abgezogen
  179. const double delta = 0.01;
  180. // Loeschen von schwachten Kanten & Finden der Attracktoren.
  181. for ( uint y = 0;y < L.getM();y++ )
  182. {
  183. for ( uint x = 0;x < L.getN();x++ )
  184. {
  185. // Pointer auf das die "Nachbarschaft"
  186. double* efirst = &L ( y, x, 0 );
  187. // Alle Kanten, die vom Knoten (y,x) abgehen
  188. valarray<double> outgoingEdges = valarray<double> ( efirst, L.getE() );
  189. // die Summe der quadratischen abgehenden Kantengewichte
  190. double edgeThreshold = pow ( outgoingEdges, 2.0 ).sum() - delta;
  191. for ( uint e = 0;e < L.getE();e++ )
  192. {
  193. if ( L ( y, x, e ) >= edgeThreshold )
  194. {
  195. M ( y, x, e ) = L ( y, x, e );
  196. }
  197. else
  198. {
  199. M ( y, x, e ) = 0.0;
  200. }
  201. if ( L ( y, x, e ) > L ( y, x, 0 ) )
  202. {
  203. M ( y, x, e ) = L ( y, x, e );
  204. }
  205. else
  206. {
  207. M ( y, x, e ) = 0.0;
  208. }
  209. }
  210. // Pointer auf das die "Nachbarschaft"
  211. efirst = &M ( y, x, 0 );
  212. // Alle Kanten, die vom Knoten (y,x) abgehen
  213. outgoingEdges = valarray<double> ( efirst, M.getE() );
  214. // die Summe der quadratischen abgehenden Kantengewichte
  215. double edgeSum = outgoingEdges.sum();
  216. if ( edgeSum == 0.0 )
  217. //if(M(y,x,0)!=0.0)
  218. {
  219. att ( y, x ) = 1.0;
  220. if ( L ( y, x, 0 ) > 0.75 )
  221. attImage.setPixel ( x, y, 255 );
  222. else if ( L ( y, x, 0 ) > 0.5 )
  223. attImage.setPixel ( x, y, 180 );
  224. else if ( L ( y, x, 0 ) > 0.25 )
  225. attImage.setPixel ( x, y, 100 );
  226. else
  227. attImage.setPixel ( x, y, 50 );
  228. }
  229. }
  230. }
  231. showImage ( attImage );
  232. printf ( "aquivalenzklassen finden\n" );
  233. for ( uint y = 0;y < att.rows();y++ )
  234. {
  235. for ( uint x = 0;x < att.cols();x++ )
  236. {
  237. // aktueller Pixel ist ein Attraktor
  238. if ( att ( y, x ) == 1.0 )
  239. {
  240. uint strongestAttIndex = 0;
  241. double strongestAttValue = 0.0;
  242. for ( uint e = 1;e < L.getE();e++ )
  243. {
  244. // "-->" Relation
  245. if ( L ( y, x, e ) > 0 )
  246. {
  247. Coord st = Coord ( y, x ) + offsets[e];
  248. if ( att ( st.first, st.second ) == 1.0 )
  249. {
  250. // benachbarter Attraktor gefunden
  251. // Welcher der beiden ist der "staerkere" ?
  252. if ( ( L ( y, x, 0 ) <= L ( st.first, st.second, 0 ) ) && ( L ( st.first, st.second, 0 ) > strongestAttValue ) )
  253. {
  254. strongestAttValue = L ( st.first, st.second, 0 );
  255. strongestAttIndex = e;
  256. }
  257. }
  258. }
  259. }
  260. if ( strongestAttIndex != 0 )
  261. {
  262. M ( y, x, strongestAttIndex ) = strongestAttValue;
  263. att ( y, x ) = 0.0;
  264. attImage.setPixel ( x, y, 0 );
  265. }
  266. }
  267. }
  268. }
  269. showImage ( attImage );
  270. //return 0;
  271. // Erste Operation auf der Ausgabemaske: Markieren der Attraktoren
  272. uint clusterCount = 0;
  273. printf ( "Attraktoren markieren\n" );
  274. //#pragma omp parallel for
  275. for ( uint y = 0;y < att.rows();y++ )
  276. {
  277. for ( uint x = 0;x < att.cols();x++ )
  278. {
  279. if ( att ( y, x ) == 1.0 )
  280. {
  281. // Jeder Attraktor bekommt eine eindeutige Identifikation & wird in der Maske markiert
  282. mask ( y, x ) = ++clusterCount;
  283. }
  284. }
  285. }
  286. printf ( "Attraktoren markiert\n" );
  287. printf ( "bla\n" );
  288. printf ( "finde cluster\n" );
  289. for ( uint y = 0;y < mask.rows();y++ )
  290. {
  291. for ( uint x = 0;x < mask.cols();x++ )
  292. {
  293. if ( mask ( y, x ) == 0.0 )
  294. {
  295. // (x,y) Pixel wurde noch keinem Cluster zugewiesen
  296. Coord st = Coord ( y, x );
  297. do
  298. {
  299. // Pointer auf das die "Nachbarschaft"
  300. const double* efirst = &M.at ( st.first, st.second, 0 );
  301. // Alle Kanten, die vom Knoten (y,x) abgehen
  302. const valarray<double> outgoingEdges = valarray<double> ( efirst, M.getE() );
  303. // maximaler Kantenwert, der von (y,x) abgeht
  304. const double maxEdgeWeight = outgoingEdges.max();
  305. // (s,t) Nachbarpixel zu dem die staerkste Kante fuerhte
  306. uint e = 0;
  307. for ( ;e < M.getE();e++ ) {
  308. if ( M ( st.first, st.second, e ) == maxEdgeWeight ) break;
  309. };
  310. st += offsets[e];
  311. //printf("(%d,%d)\n",st.second,st.first);
  312. } while ( att ( st.first, st.second ) == 0.0 );
  313. mask ( y, x ) = mask ( st.first, st.second );
  314. }
  315. }
  316. }
  317. //showImage(att);
  318. return clusterCount;
  319. //printf("[log] start clustering\n");
  320. // erzeuge den DAG fuer die L-Matrix. Dh. es werden nur Kanten behalten, welche folgendes Kriterium erfuellen:
  321. // seien A,B Knoten aus V und sei w(*) das Gewicht der Kante der beiden Knoten. Dann enthaelt der DAG nur die
  322. // Kanten, fuer die gilt: w(A->B)>w(A->A). Dabei entstehen senken, welche welche von den Attracktoren gebildet
  323. // werden, da diese diese Bedingung nicht erfüllen. Dieses Vorgehen erzeugt ein ueberlappendes Clustering, dass
  324. // in der Bildsegmentierung nicht gewuenscht ist. Darum wird der DAG wie folgt erweitert:
  325. // Def. siehe oben. Zusaetzliche Bedingung ist, dass w(A->B) die staerkste abgehende Kante von A ist.
  326. // Maske zum Speichern der max. Kante. Dabei wird der entsprechende Offsetindex gespeichert.
  327. //Matrix maxEdgeIndexMatrix(L.getM(),L.getN(),-1);
  328. /*
  329. #pragma omp parallel for
  330. for(uint y=0;y<L.getM();y++)
  331. {
  332. for(uint x=0;x<L.getN();x++)
  333. {
  334. // Pointer auf das die "Nachbarschaft"
  335. double* efirst=&L.at(y,x,0);
  336. // Alle Kanten, die vom Knoten (y,x) abgehen
  337. valarray<double> outgoingEdges=valarray<double>(efirst,L.getE());
  338. // maximaler Kantenwert, der von (y,x) abgeht
  339. double maxEdgeWeight=outgoingEdges.max();
  340. if(maxEdgeWeight==0.5) printf("[debug] max. edgeweight=%.2f\n",maxEdgeWeight);
  341. // Alle Kanten loeschen, die kleineres Gewicht als
  342. for(uint e=0;e<L.getE();e++)
  343. {
  344. if(L.at(y,x,e)!=maxEdgeWeight)
  345. {
  346. L.at(y,x,e)=0.0;
  347. }
  348. else
  349. {
  350. // Index der maximalen Kante wird gespeichert.
  351. maxEdgeIndexMatrix(y,x)=e;
  352. }
  353. }
  354. }
  355. }
  356. */
  357. /*
  358. for(uint y=0;y<L.getM();y++)
  359. {
  360. for(uint x=0;x<L.getN();x++)
  361. {
  362. // wenn es sich um einen Attracktor handelt, dann ist der Eintrag in der maxEdgeIndexMatrix=0
  363. if(maxEdgeIndexMatrix(y,x)==0)
  364. {
  365. clusterCount++;
  366. mask(y,x)=indexOfPixel(Coord(y,x),L.getN());
  367. continue;
  368. }
  369. Coord st(y,x);
  370. do
  371. {
  372. // Update st auf die Koordinaten des Knotens zu dem die staerkste Kante geht.
  373. st+=offsets[maxEdgeIndexMatrix(st.first,st.second)];
  374. // Wir sind auf einen Pixel gestossen, der bereits markiert ist.
  375. if(mask(st.first,st.second)!=(-1))
  376. {
  377. mask(y,x)=mask(st.first,st.second);
  378. break;
  379. }
  380. }while(maxEdgeIndexMatrix(st.first,st.second)!=0);
  381. if(mask(y,x)==(-1)) mask(y,x)=indexOfPixel(st,L.getN());
  382. }
  383. }*/
  384. //return clusterCount;
  385. }
  386. inline uint
  387. RSMarkovCluster::indexOfPixel ( const Coord& yx, const uint xSize ) const
  388. {
  389. return yx.first*xSize + yx.second;
  390. }
  391. void
  392. RSMarkovCluster::normalize ( NodeCentricRepMatrix& L ) const
  393. {
  394. #pragma omp parallel for
  395. for ( uint y = 0;y < L.getM();y++ )
  396. {
  397. for ( uint x = 0;x < L.getN();x++ )
  398. {
  399. // Pointer auf das die "Nachbarschaft"
  400. double* efirst = &L ( y, x, 0 );
  401. // Alle Kanten, die vom Knoten (y,x) abgehen
  402. valarray<double> outgoingEdges = valarray<double> ( efirst, L.getE() );
  403. // maximaler Kantenwert, der von (y,x) abgeht
  404. double sum = outgoingEdges.sum();
  405. for ( uint e = 0;e < L.getE();e++ )
  406. {
  407. L ( y, x, e ) = checkForNAN ( L ( y, x, e ) / sum );
  408. }
  409. }
  410. }
  411. }
  412. void
  413. RSMarkovCluster::inflation ( const NodeCentricRepMatrix& Lin, NodeCentricRepMatrix& Lout ) const
  414. {
  415. #pragma omp parallel for
  416. for ( uint y = 0;y < Lin.getM();y++ )
  417. {
  418. for ( uint x = 0;x < Lin.getN();x++ )
  419. {
  420. for ( uint e = 0;e < Lin.getE();e++ )
  421. {
  422. Lout ( y, x, e ) = checkForNAN ( pow ( Lin ( y, x, e ), this->p ) );
  423. }
  424. }
  425. }
  426. }
  427. void
  428. RSMarkovCluster::expansion ( const NodeCentricRepMatrix& Lin, NodeCentricRepMatrix& Lout, const Offsets& offsets, const Detours& detours ) const
  429. {
  430. #pragma omp parallel for
  431. for ( uint y = 0;y < Lin.getM();y++ )
  432. {
  433. for ( uint x = 0;x < Lin.getN();x++ )
  434. {
  435. // neues Kantengewicht fuer alle "adjazenten" Knoten berechnen
  436. for ( uint e = 0;e < Lin.getE();e++ )
  437. {
  438. double w_xy_mn = 0.0;
  439. for ( uint d = 0;d < detours[e].size();d++ )
  440. {
  441. uint efirst = detours[e][d].first;
  442. uint esecond = detours[e][d].second;
  443. Coord st = Coord ( y, x ) + offsets[efirst];
  444. double w_xy_st = 0.0;
  445. double w_st_mn = 0.0;
  446. if ( ( st.first >= 0 ) && ( st.first < (int)Lin.getM() ) && ( st.second >= 0 ) && ( st.second < (int)Lin.getN() ) )
  447. {
  448. w_xy_st = Lin ( y, x, efirst );
  449. w_st_mn = Lin ( st.first, st.second, esecond );
  450. }
  451. w_xy_mn += w_xy_st * w_st_mn;
  452. }
  453. Lout ( y, x, e ) = checkForNAN ( w_xy_mn );
  454. }
  455. }
  456. }
  457. }
  458. inline double
  459. RSMarkovCluster::checkForNAN ( const double val ) const
  460. {
  461. if ( ! ( val == val ) || ( val == -std::numeric_limits < double >::quiet_NaN () ) )
  462. return 0.0;
  463. else
  464. return val;
  465. }
  466. void
  467. RSMarkovCluster::runClustering ( const RSMarkovCluster::Offsets& offsets, const RSMarkovCluster::Detours& detours, NodeCentricRepMatrix& L1 ) const
  468. {
  469. //printMatrix(L1,offsets,"Linit");
  470. // Initialisierte Markovmatrix muss normalisiert werden.
  471. normalize ( L1 );
  472. // Mass fuer die Aenderungen innerhalb der Matrix.
  473. //double chaos = 1.0;
  474. //uint sameChaosCounter = 0; // Wenn sich Chaos eine bestimmte Anzahl von Iterationen nicht mehr veraendert, dann wird abgebrochen.
  475. // 2te Markovmatrix zum Vergleichen der Veraenderungen
  476. NodeCentricRepMatrix L2 ( L1.getM(), L1.getN(), L1.getE() );
  477. uint iterationCounter = 0;
  478. #ifdef DEBUGMODE
  479. time_duration expAvgTime ( 0, 0, 0, 0 );
  480. time_duration infAvgTime ( 0, 0, 0, 0 );
  481. time_duration norAvgTime ( 0, 0, 0, 0 );
  482. #endif
  483. printf ( "%d\n", iterations );
  484. //while(chaos>chaosThreshold)
  485. while ( iterationCounter < (uint)iterations )
  486. {
  487. #ifdef DEBUGMODE
  488. // Anfangszeitpunkt
  489. ptime start ( microsec_clock::local_time() ); //
  490. #endif
  491. // rufe Matrix L1 und speichere in Matrix L2 (L2<--exp(L1))
  492. expansion ( L1, L2, offsets, detours );
  493. #ifdef DEBUGMODE
  494. // Endzeitpunkt
  495. ptime end ( microsec_clock::local_time() ); //
  496. // Zeit, die der Expansionschritt gebraucht hat.
  497. time_duration expDuration ( end - start );
  498. printf ( "[log] expansion: %ld.%3ldsek\n", expDuration.total_milliseconds() / 1000, expDuration.total_milliseconds() % 1000 );
  499. // Gesamtlaufzeit des Expansionschritts
  500. expAvgTime += expDuration;
  501. #endif
  502. #ifdef DEBUGMODE
  503. // Anfangszeitpunkt
  504. start = microsec_clock::local_time(); //
  505. #endif
  506. // rufe Matrix L2 und speichere in Matrix L1 (L1<--inf(L2))
  507. inflation ( L2, L1 );
  508. #ifdef DEBUGMODE
  509. // Endzeitpunkt
  510. end = microsec_clock::local_time(); //
  511. // Zeit, die der Expansionschritt gebraucht hat.
  512. time_duration infDuration ( end - start );
  513. printf ( "[log] inflation: %ld.%3ldsek\n", infDuration.total_milliseconds() / 1000, infDuration.total_milliseconds() % 1000 );
  514. // Gesamtlaufzeit des Expansionschritts
  515. infAvgTime += infDuration;
  516. #endif
  517. #ifdef DEBUGMODE
  518. // Anfangszeitpunkt
  519. start = microsec_clock::local_time(); //
  520. #endif
  521. // vor dem Ende jeder Iteration muss normalisiert werden.
  522. normalize ( L1 );
  523. #ifdef DEBUGMODE
  524. // Endzeitpunkt
  525. end = microsec_clock::local_time(); //
  526. // Zeit, die der Expansionschritt gebraucht hat.
  527. time_duration norDuration ( end - start );
  528. printf ( "[log] normalize: %ld.%3ldsek\n", norDuration.total_milliseconds() / 1000, norDuration.total_milliseconds() % 1000 );
  529. // Gesamtlaufzeit des Expansionschritts
  530. norAvgTime += norDuration;
  531. #endif
  532. //double lastChaos=chaos;
  533. // berechne die Veraenderungen der Matrix nach dem Schritt t
  534. //double maxDiffValue=NodeCentricRepMatrix::maxValue(L1-L2);
  535. //chaos=min(maxDiffValue,chaos);
  536. //printf("[log] %d iteration: chaos=%.5f\n",iterationCounter,chaos);
  537. //printf("[debug] %.5f\n",maxDiffValue);
  538. iterationCounter++;
  539. printf ( "[log] %d. Iteration\n", iterationCounter );
  540. /*
  541. if(lastChaos==chaos)
  542. {
  543. sameChaosCounter++;
  544. if(sameChaosCounter==maxConstantInteration)
  545. {
  546. break;
  547. }
  548. }
  549. else
  550. {
  551. sameChaosCounter=0;
  552. }
  553. */
  554. }
  555. #ifdef DEBUGMODE
  556. long int expAvgTimeUSec = expAvgTime.total_milliseconds() / ( iterationCounter - 1 );
  557. long int infAvgTimeUSec = infAvgTime.total_milliseconds() / ( iterationCounter - 1 );
  558. long int norAvgTimeUSec = norAvgTime.total_milliseconds() / ( iterationCounter - 1 );
  559. printf ( "[log] Durchschnittszeit fuer Expansion: %ld.%3ldsek\n", expAvgTimeUSec / 1000, expAvgTimeUSec % 1000 );
  560. printf ( "[log] Durchschnittszeit fuer Inflation: %ld.%3ldsek\n", infAvgTimeUSec / 1000, infAvgTimeUSec % 1000 );
  561. printf ( "[log] Durchschnittszeit fuer Normalize: %ld.%3ldsek\n", norAvgTimeUSec / 1000, norAvgTimeUSec % 1000 );
  562. #endif
  563. }
  564. void
  565. RSMarkovCluster::initMarkovMatrix ( const uchar* imageData, const uint imageHeight, const uint imageWidth, const uint channelCount, const RSMarkovCluster::Offsets& offsets, NodeCentricRepMatrix& L ) const
  566. {
  567. // Initialisierung erfolgt fuer jeden Pixel und die 8er Nachbarschaft. Dabei wird im Loops initialisiert.
  568. #pragma omp parallel for
  569. for ( uint y = 0;y < imageHeight;y++ )
  570. {
  571. for ( uint x = 0;x < imageWidth;x++ )
  572. {
  573. for ( uint e = 0; e < 9; e++ )
  574. {
  575. // Koordinaten des Nachbarpixels
  576. RSMarkovCluster::Coord yxN = RSMarkovCluster::Coord ( y, x ) + offsets[e];
  577. // Eine Verbindung zu einem Nachbarn ausserhalb des Bildes hat das Gewicht 0.
  578. if ( ( yxN.first < 0 ) || ( yxN.first >= (int)imageHeight ) || ( yxN.second < 0 ) || ( yxN.second >= (int)imageWidth ) )
  579. continue;
  580. Vector imageValue ( channelCount );
  581. for ( uint c = 0;c < channelCount;c++ )
  582. {
  583. uint indexP = y * imageWidth * channelCount + x * channelCount + c;
  584. uint indexN = yxN.first * imageWidth * channelCount + yxN.second * channelCount + c;
  585. imageValue[c] = ( double ( imageData[indexP] ) - double ( imageData[indexN] ) ) / 255.0;
  586. }
  587. L.at ( y, x, e ) = edgeWeight ( imageValue );
  588. }
  589. }
  590. }
  591. }
  592. inline double
  593. RSMarkovCluster::edgeWeight ( const Vector& imageValueDiff ) const
  594. {
  595. return exp ( - ( this->mu ) * pow ( imageValueDiff.normL2 (), 2 ) );
  596. }
  597. void
  598. RSMarkovCluster::printMatrix ( const NodeCentricRepMatrix& L, const RSMarkovCluster::Offsets& offsets , const string& filename ) const
  599. {
  600. // Bemerkung in Offset ist [0]=x && [1]=y
  601. const uint n_x = L.getN ();
  602. const uint n_y = L.getM ();
  603. const uint n_e = L.getE ();
  604. Matrix oMatrix ( ( n_y*n_x ), ( n_y*n_x ) );
  605. Matrix::iterator it = oMatrix.begin();
  606. for ( ;it != oMatrix.end();++it ) {
  607. ( *it ) = 0;
  608. }
  609. for ( uint y = 0;y < n_y;y++ )
  610. {
  611. for ( uint x = 0;x < n_x;x++ )
  612. {
  613. for ( uint e = 0;e < n_e;e++ )
  614. {
  615. double value = L.at ( y, x, e );
  616. int n = offsets[e].second;
  617. int m = offsets[e].first;
  618. int indexP = y * n_x + x;
  619. int indexN = ( y + m ) * n_x + ( x + n );
  620. if ( ( indexP >= 0 ) && ( indexP < ( n_y*n_x ) ) && ( indexN >= 0 ) && ( indexN < ( n_y*n_x ) ) )
  621. oMatrix ( indexP, indexN ) = value;
  622. }
  623. }
  624. }
  625. ofstream fout;
  626. fout.open ( filename.c_str() );
  627. for ( int y = 0;y < ( n_y*n_x );y++ )
  628. {
  629. string line = "";
  630. for ( int x = 0;x < ( n_y*n_x );x++ )
  631. {
  632. if ( oMatrix ( x, y ) == 0.0 ) line += "----\t";
  633. else
  634. {
  635. char entry[16];
  636. sprintf ( entry, "%.3f\t", oMatrix ( x, y ) );
  637. line += string ( entry );
  638. }
  639. }
  640. fout << line << endl;
  641. }
  642. fout.close();
  643. }