RSMarkovCluster.cpp 26 KB

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