SLIC.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. // SLIC.cpp: implementation of the SLIC class.
  2. //
  3. // Copyright (C) Radhakrishna Achanta 2012
  4. // All rights reserved
  5. // Email: firstname.lastname@epfl.ch
  6. //////////////////////////////////////////////////////////////////////
  7. //#include "stdafx.h"
  8. #include <cfloat>
  9. #include <cmath>
  10. #include <iostream>
  11. #include <fstream>
  12. #include "SLIC.h"
  13. //////////////////////////////////////////////////////////////////////
  14. // Construction/Destruction
  15. //////////////////////////////////////////////////////////////////////
  16. SLIC::SLIC()
  17. {
  18. m_lvec = NULL;
  19. m_avec = NULL;
  20. m_bvec = NULL;
  21. m_lvecvec = NULL;
  22. m_avecvec = NULL;
  23. m_bvecvec = NULL;
  24. }
  25. SLIC::~SLIC()
  26. {
  27. if (m_lvec) delete [] m_lvec;
  28. if (m_avec) delete [] m_avec;
  29. if (m_bvec) delete [] m_bvec;
  30. if (m_lvecvec)
  31. {
  32. for ( int d = 0; d < m_depth; d++ ) delete [] m_lvecvec[d];
  33. delete [] m_lvecvec;
  34. }
  35. if (m_avecvec)
  36. {
  37. for ( int d = 0; d < m_depth; d++ ) delete [] m_avecvec[d];
  38. delete [] m_avecvec;
  39. }
  40. if (m_bvecvec)
  41. {
  42. for ( int d = 0; d < m_depth; d++ ) delete [] m_bvecvec[d];
  43. delete [] m_bvecvec;
  44. }
  45. }
  46. //==============================================================================
  47. /// RGB2XYZ
  48. ///
  49. /// sRGB (D65 illuninant assumption) to XYZ conversion
  50. //==============================================================================
  51. void SLIC::RGB2XYZ(
  52. const int& sR,
  53. const int& sG,
  54. const int& sB,
  55. double& X,
  56. double& Y,
  57. double& Z)
  58. {
  59. double R = sR/255.0;
  60. double G = sG/255.0;
  61. double B = sB/255.0;
  62. double r, g, b;
  63. if (R <= 0.04045) r = R/12.92;
  64. else r = pow((R+0.055)/1.055,2.4);
  65. if (G <= 0.04045) g = G/12.92;
  66. else g = pow((G+0.055)/1.055,2.4);
  67. if (B <= 0.04045) b = B/12.92;
  68. else b = pow((B+0.055)/1.055,2.4);
  69. X = r*0.4124564 + g*0.3575761 + b*0.1804375;
  70. Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
  71. Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
  72. }
  73. //===========================================================================
  74. /// RGB2LAB
  75. //===========================================================================
  76. void SLIC::RGB2LAB(const int& sR, const int& sG, const int& sB, double& lval, double& aval, double& bval)
  77. {
  78. //------------------------
  79. // sRGB to XYZ conversion
  80. //------------------------
  81. double X, Y, Z;
  82. RGB2XYZ(sR, sG, sB, X, Y, Z);
  83. //------------------------
  84. // XYZ to LAB conversion
  85. //------------------------
  86. double epsilon = 0.008856; //actual CIE standard
  87. double kappa = 903.3; //actual CIE standard
  88. double Xr = 0.950456; //reference white
  89. double Yr = 1.0; //reference white
  90. double Zr = 1.088754; //reference white
  91. double xr = X/Xr;
  92. double yr = Y/Yr;
  93. double zr = Z/Zr;
  94. double fx, fy, fz;
  95. if (xr > epsilon) fx = pow(xr, 1.0/3.0);
  96. else fx = (kappa*xr + 16.0)/116.0;
  97. if (yr > epsilon) fy = pow(yr, 1.0/3.0);
  98. else fy = (kappa*yr + 16.0)/116.0;
  99. if (zr > epsilon) fz = pow(zr, 1.0/3.0);
  100. else fz = (kappa*zr + 16.0)/116.0;
  101. lval = 116.0*fy-16.0;
  102. aval = 500.0*(fx-fy);
  103. bval = 200.0*(fy-fz);
  104. }
  105. //===========================================================================
  106. /// DoRGBtoLABConversion
  107. ///
  108. /// For whole image: overlaoded floating point version
  109. //===========================================================================
  110. void SLIC::DoRGBtoLABConversion(
  111. const unsigned int*& ubuff,
  112. double*& lvec,
  113. double*& avec,
  114. double*& bvec)
  115. {
  116. int sz = m_width*m_height;
  117. lvec = new double[sz];
  118. avec = new double[sz];
  119. bvec = new double[sz];
  120. for ( int j = 0; j < sz; j++ )
  121. {
  122. int r = (ubuff[j] >> 16) & 0xFF;
  123. int g = (ubuff[j] >> 8) & 0xFF;
  124. int b = (ubuff[j] ) & 0xFF;
  125. RGB2LAB( r, g, b, lvec[j], avec[j], bvec[j] );
  126. }
  127. }
  128. //===========================================================================
  129. /// DoRGBtoLABConversion
  130. ///
  131. /// For whole volume
  132. //===========================================================================
  133. void SLIC::DoRGBtoLABConversion(
  134. unsigned int**& ubuff,
  135. double**& lvec,
  136. double**& avec,
  137. double**& bvec)
  138. {
  139. int sz = m_width*m_height;
  140. for ( int d = 0; d < m_depth; d++ )
  141. {
  142. for ( int j = 0; j < sz; j++ )
  143. {
  144. int r = (ubuff[d][j] >> 16) & 0xFF;
  145. int g = (ubuff[d][j] >> 8) & 0xFF;
  146. int b = (ubuff[d][j] ) & 0xFF;
  147. RGB2LAB( r, g, b, lvec[d][j], avec[d][j], bvec[d][j] );
  148. }
  149. }
  150. }
  151. //=================================================================================
  152. /// DrawContoursAroundSegments
  153. ///
  154. /// Internal contour drawing option exists. One only needs to comment the if
  155. /// statement inside the loop that looks at neighbourhood.
  156. //=================================================================================
  157. void SLIC::DrawContoursAroundSegments(
  158. unsigned int*& ubuff,
  159. int*& labels,
  160. const int& width,
  161. const int& height,
  162. const unsigned int& color )
  163. {
  164. const int dx8[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
  165. const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1, 1};
  166. /* int sz = width*height;
  167. vector<bool> istaken(sz, false);
  168. int mainindex(0);
  169. for( int j = 0; j < height; j++ )
  170. {
  171. for( int k = 0; k < width; k++ )
  172. {
  173. int np(0);
  174. for( int i = 0; i < 8; i++ )
  175. {
  176. int x = k + dx8[i];
  177. int y = j + dy8[i];
  178. if( (x >= 0 && x < width) && (y >= 0 && y < height) )
  179. {
  180. int index = y*width + x;
  181. if( false == istaken[index] )//comment this to obtain internal contours
  182. {
  183. if( labels[mainindex] != labels[index] ) np++;
  184. }
  185. }
  186. }
  187. if( np > 1 )//change to 2 or 3 for thinner lines
  188. {
  189. ubuff[mainindex] = color;
  190. istaken[mainindex] = true;
  191. }
  192. mainindex++;
  193. }
  194. }*/
  195. int sz = width*height;
  196. vector<bool> istaken(sz, false);
  197. vector<int> contourx(sz);
  198. vector<int> contoury(sz);
  199. int mainindex(0);
  200. int cind(0);
  201. for ( int j = 0; j < height; j++ )
  202. {
  203. for ( int k = 0; k < width; k++ )
  204. {
  205. int np(0);
  206. for ( int i = 0; i < 8; i++ )
  207. {
  208. int x = k + dx8[i];
  209. int y = j + dy8[i];
  210. if ( (x >= 0 && x < width) && (y >= 0 && y < height) )
  211. {
  212. int index = y*width + x;
  213. //if( false == istaken[index] )//comment this to obtain internal contours
  214. {
  215. if ( labels[mainindex] != labels[index] ) np++;
  216. }
  217. }
  218. }
  219. if ( np > 1 )
  220. {
  221. contourx[cind] = k;
  222. contoury[cind] = j;
  223. istaken[mainindex] = true;
  224. //img[mainindex] = color;
  225. cind++;
  226. }
  227. mainindex++;
  228. }
  229. }
  230. int numboundpix = cind;//int(contourx.size());
  231. for ( int j = 0; j < numboundpix; j++ )
  232. {
  233. int ii = contoury[j]*width + contourx[j];
  234. ubuff[ii] = 0xffffff;
  235. for ( int n = 0; n < 8; n++ )
  236. {
  237. int x = contourx[j] + dx8[n];
  238. int y = contoury[j] + dy8[n];
  239. if ( (x >= 0 && x < width) && (y >= 0 && y < height) )
  240. {
  241. int ind = y*width + x;
  242. if (!istaken[ind]) ubuff[ind] = 0;
  243. }
  244. }
  245. }
  246. }
  247. //==============================================================================
  248. /// DetectLabEdges
  249. //==============================================================================
  250. void SLIC::DetectLabEdges(
  251. const double* lvec,
  252. const double* avec,
  253. const double* bvec,
  254. const int& width,
  255. const int& height,
  256. vector<double>& edges)
  257. {
  258. int sz = width*height;
  259. edges.resize(sz,0);
  260. for ( int j = 1; j < height-1; j++ )
  261. {
  262. for ( int k = 1; k < width-1; k++ )
  263. {
  264. int i = j*width+k;
  265. double dx = (lvec[i-1]-lvec[i+1])*(lvec[i-1]-lvec[i+1]) +
  266. (avec[i-1]-avec[i+1])*(avec[i-1]-avec[i+1]) +
  267. (bvec[i-1]-bvec[i+1])*(bvec[i-1]-bvec[i+1]);
  268. double dy = (lvec[i-width]-lvec[i+width])*(lvec[i-width]-lvec[i+width]) +
  269. (avec[i-width]-avec[i+width])*(avec[i-width]-avec[i+width]) +
  270. (bvec[i-width]-bvec[i+width])*(bvec[i-width]-bvec[i+width]);
  271. //edges[i] = fabs(dx) + fabs(dy);
  272. edges[i] = dx*dx + dy*dy;
  273. }
  274. }
  275. }
  276. //===========================================================================
  277. /// PerturbSeeds
  278. //===========================================================================
  279. void SLIC::PerturbSeeds(
  280. vector<double>& kseedsl,
  281. vector<double>& kseedsa,
  282. vector<double>& kseedsb,
  283. vector<double>& kseedsx,
  284. vector<double>& kseedsy,
  285. const vector<double>& edges)
  286. {
  287. const int dx8[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
  288. const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1, 1};
  289. int numseeds = kseedsl.size();
  290. for ( int n = 0; n < numseeds; n++ )
  291. {
  292. int ox = kseedsx[n];//original x
  293. int oy = kseedsy[n];//original y
  294. int oind = oy*m_width + ox;
  295. int storeind = oind;
  296. for ( int i = 0; i < 8; i++ )
  297. {
  298. int nx = ox+dx8[i];//new x
  299. int ny = oy+dy8[i];//new y
  300. if ( nx >= 0 && nx < m_width && ny >= 0 && ny < m_height)
  301. {
  302. int nind = ny*m_width + nx;
  303. if ( edges[nind] < edges[storeind])
  304. {
  305. storeind = nind;
  306. }
  307. }
  308. }
  309. if (storeind != oind)
  310. {
  311. kseedsx[n] = storeind%m_width;
  312. kseedsy[n] = storeind/m_width;
  313. kseedsl[n] = m_lvec[storeind];
  314. kseedsa[n] = m_avec[storeind];
  315. kseedsb[n] = m_bvec[storeind];
  316. }
  317. }
  318. }
  319. //===========================================================================
  320. /// GetLABXYSeeds_ForGivenStepSize
  321. ///
  322. /// The k seed values are taken as uniform spatial pixel samples.
  323. //===========================================================================
  324. void SLIC::GetLABXYSeeds_ForGivenStepSize(
  325. vector<double>& kseedsl,
  326. vector<double>& kseedsa,
  327. vector<double>& kseedsb,
  328. vector<double>& kseedsx,
  329. vector<double>& kseedsy,
  330. const int& STEP,
  331. const bool& perturbseeds,
  332. const vector<double>& edgemag)
  333. {
  334. const bool hexgrid = false;
  335. int numseeds(0);
  336. int n(0);
  337. //int xstrips = m_width/STEP;
  338. //int ystrips = m_height/STEP;
  339. int xstrips = (0.5+double(m_width)/double(STEP));
  340. int ystrips = (0.5+double(m_height)/double(STEP));
  341. int xerr = m_width - STEP*xstrips;
  342. if (xerr < 0) {
  343. xstrips--;
  344. xerr = m_width - STEP*xstrips;
  345. }
  346. int yerr = m_height - STEP*ystrips;
  347. if (yerr < 0) {
  348. ystrips--;
  349. yerr = m_height- STEP*ystrips;
  350. }
  351. double xerrperstrip = double(xerr)/double(xstrips);
  352. double yerrperstrip = double(yerr)/double(ystrips);
  353. int xoff = STEP/2;
  354. int yoff = STEP/2;
  355. //-------------------------
  356. numseeds = xstrips*ystrips;
  357. //-------------------------
  358. kseedsl.resize(numseeds);
  359. kseedsa.resize(numseeds);
  360. kseedsb.resize(numseeds);
  361. kseedsx.resize(numseeds);
  362. kseedsy.resize(numseeds);
  363. for ( int y = 0; y < ystrips; y++ )
  364. {
  365. int ye = y*yerrperstrip;
  366. for ( int x = 0; x < xstrips; x++ )
  367. {
  368. int xe = x*xerrperstrip;
  369. int seedx = (x*STEP+xoff+xe);
  370. if (hexgrid) {
  371. seedx = x*STEP+(xoff<<(y&0x1))+xe; //for hex grid sampling
  372. seedx = min(m_width-1,seedx);
  373. }
  374. int seedy = (y*STEP+yoff+ye);
  375. int i = seedy*m_width + seedx;
  376. kseedsl[n] = m_lvec[i];
  377. kseedsa[n] = m_avec[i];
  378. kseedsb[n] = m_bvec[i];
  379. kseedsx[n] = seedx;
  380. kseedsy[n] = seedy;
  381. n++;
  382. }
  383. }
  384. if (perturbseeds)
  385. {
  386. PerturbSeeds(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, edgemag);
  387. }
  388. }
  389. //===========================================================================
  390. /// GetKValues_LABXYZ
  391. ///
  392. /// The k seed values are taken as uniform spatial pixel samples.
  393. //===========================================================================
  394. void SLIC::GetKValues_LABXYZ(
  395. vector<double>& kseedsl,
  396. vector<double>& kseedsa,
  397. vector<double>& kseedsb,
  398. vector<double>& kseedsx,
  399. vector<double>& kseedsy,
  400. vector<double>& kseedsz,
  401. const int& STEP)
  402. {
  403. const bool hexgrid = false;
  404. int numseeds(0);
  405. int n(0);
  406. int xstrips = (0.5+double(m_width)/double(STEP));
  407. int ystrips = (0.5+double(m_height)/double(STEP));
  408. int zstrips = (0.5+double(m_depth)/double(STEP));
  409. int xerr = m_width - STEP*xstrips;
  410. if (xerr < 0) {
  411. xstrips--;
  412. xerr = m_width - STEP*xstrips;
  413. }
  414. int yerr = m_height - STEP*ystrips;
  415. if (yerr < 0) {
  416. ystrips--;
  417. yerr = m_height- STEP*ystrips;
  418. }
  419. int zerr = m_depth - STEP*zstrips;
  420. if (zerr < 0) {
  421. zstrips--;
  422. zerr = m_depth - STEP*zstrips;
  423. }
  424. double xerrperstrip = double(xerr)/double(xstrips);
  425. double yerrperstrip = double(yerr)/double(ystrips);
  426. double zerrperstrip = double(zerr)/double(zstrips);
  427. int xoff = STEP/2;
  428. int yoff = STEP/2;
  429. int zoff = STEP/2;
  430. //-------------------------
  431. numseeds = xstrips*ystrips*zstrips;
  432. //-------------------------
  433. kseedsl.resize(numseeds);
  434. kseedsa.resize(numseeds);
  435. kseedsb.resize(numseeds);
  436. kseedsx.resize(numseeds);
  437. kseedsy.resize(numseeds);
  438. kseedsz.resize(numseeds);
  439. for ( int z = 0; z < zstrips; z++ )
  440. {
  441. int ze = z*zerrperstrip;
  442. int d = (z*STEP+zoff+ze);
  443. for ( int y = 0; y < ystrips; y++ )
  444. {
  445. int ye = y*yerrperstrip;
  446. for ( int x = 0; x < xstrips; x++ )
  447. {
  448. int xe = x*xerrperstrip;
  449. int i = (y*STEP+yoff+ye)*m_width + (x*STEP+xoff+xe);
  450. kseedsl[n] = m_lvecvec[d][i];
  451. kseedsa[n] = m_avecvec[d][i];
  452. kseedsb[n] = m_bvecvec[d][i];
  453. kseedsx[n] = (x*STEP+xoff+xe);
  454. kseedsy[n] = (y*STEP+yoff+ye);
  455. kseedsz[n] = d;
  456. n++;
  457. }
  458. }
  459. }
  460. }
  461. //===========================================================================
  462. /// PerformSuperpixelSLIC
  463. ///
  464. /// Performs k mean segmentation. It is fast because it looks locally, not
  465. /// over the entire image.
  466. //===========================================================================
  467. void SLIC::PerformSuperpixelSLIC(
  468. vector<double>& kseedsl,
  469. vector<double>& kseedsa,
  470. vector<double>& kseedsb,
  471. vector<double>& kseedsx,
  472. vector<double>& kseedsy,
  473. int*& klabels,
  474. const int& STEP,
  475. const vector<double>& edgemag,
  476. const double& M)
  477. {
  478. int sz = m_width*m_height;
  479. const int numk = kseedsl.size();
  480. //----------------
  481. int offset = STEP;
  482. //if(STEP < 8) offset = STEP*1.5;//to prevent a crash due to a very small step size
  483. //----------------
  484. vector<double> clustersize(numk, 0);
  485. vector<double> inv(numk, 0);//to store 1/clustersize[k] values
  486. vector<double> sigmal(numk, 0);
  487. vector<double> sigmaa(numk, 0);
  488. vector<double> sigmab(numk, 0);
  489. vector<double> sigmax(numk, 0);
  490. vector<double> sigmay(numk, 0);
  491. vector<double> distvec(sz, DBL_MAX);
  492. double invwt = 1.0/((STEP/M)*(STEP/M));
  493. int x1, y1, x2, y2;
  494. double l, a, b;
  495. double dist;
  496. double distxy;
  497. for ( int itr = 0; itr < 10; itr++ )
  498. {
  499. distvec.assign(sz, DBL_MAX);
  500. for ( int n = 0; n < numk; n++ )
  501. {
  502. y1 = max(0.0, kseedsy[n]-offset);
  503. y2 = min((double)m_height, kseedsy[n]+offset);
  504. x1 = max(0.0, kseedsx[n]-offset);
  505. x2 = min((double)m_width, kseedsx[n]+offset);
  506. for ( int y = y1; y < y2; y++ )
  507. {
  508. for ( int x = x1; x < x2; x++ )
  509. {
  510. int i = y*m_width + x;
  511. l = m_lvec[i];
  512. a = m_avec[i];
  513. b = m_bvec[i];
  514. dist = (l - kseedsl[n])*(l - kseedsl[n]) +
  515. (a - kseedsa[n])*(a - kseedsa[n]) +
  516. (b - kseedsb[n])*(b - kseedsb[n]);
  517. distxy = (x - kseedsx[n])*(x - kseedsx[n]) +
  518. (y - kseedsy[n])*(y - kseedsy[n]);
  519. //------------------------------------------------------------------------
  520. dist += distxy*invwt;//dist = sqrt(dist) + sqrt(distxy*invwt);//this is more exact
  521. //------------------------------------------------------------------------
  522. if ( dist < distvec[i] )
  523. {
  524. distvec[i] = dist;
  525. klabels[i] = n;
  526. }
  527. }
  528. }
  529. }
  530. //-----------------------------------------------------------------
  531. // Recalculate the centroid and store in the seed values
  532. //-----------------------------------------------------------------
  533. //instead of reassigning memory on each iteration, just reset.
  534. sigmal.assign(numk, 0);
  535. sigmaa.assign(numk, 0);
  536. sigmab.assign(numk, 0);
  537. sigmax.assign(numk, 0);
  538. sigmay.assign(numk, 0);
  539. clustersize.assign(numk, 0);
  540. //------------------------------------
  541. //edgesum.assign(numk, 0);
  542. //------------------------------------
  543. {
  544. int ind(0);
  545. for ( int r = 0; r < m_height; r++ )
  546. {
  547. for ( int c = 0; c < m_width; c++ )
  548. {
  549. sigmal[klabels[ind]] += m_lvec[ind];
  550. sigmaa[klabels[ind]] += m_avec[ind];
  551. sigmab[klabels[ind]] += m_bvec[ind];
  552. sigmax[klabels[ind]] += c;
  553. sigmay[klabels[ind]] += r;
  554. //------------------------------------
  555. //edgesum[klabels[ind]] += edgemag[ind];
  556. //------------------------------------
  557. clustersize[klabels[ind]] += 1.0;
  558. ind++;
  559. }
  560. }
  561. }
  562. {
  563. for ( int k = 0; k < numk; k++ )
  564. {
  565. if ( clustersize[k] <= 0 ) clustersize[k] = 1;
  566. inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
  567. }
  568. }
  569. {
  570. for ( int k = 0; k < numk; k++ )
  571. {
  572. kseedsl[k] = sigmal[k]*inv[k];
  573. kseedsa[k] = sigmaa[k]*inv[k];
  574. kseedsb[k] = sigmab[k]*inv[k];
  575. kseedsx[k] = sigmax[k]*inv[k];
  576. kseedsy[k] = sigmay[k]*inv[k];
  577. //------------------------------------
  578. //edgesum[k] *= inv[k];
  579. //------------------------------------
  580. }
  581. }
  582. }
  583. }
  584. //===========================================================================
  585. /// PerformSupervoxelSLIC
  586. ///
  587. /// Performs k mean segmentation. It is fast because it searches locally, not
  588. /// over the entire image.
  589. //===========================================================================
  590. void SLIC::PerformSupervoxelSLIC(
  591. vector<double>& kseedsl,
  592. vector<double>& kseedsa,
  593. vector<double>& kseedsb,
  594. vector<double>& kseedsx,
  595. vector<double>& kseedsy,
  596. vector<double>& kseedsz,
  597. int**& klabels,
  598. const int& STEP,
  599. const double& compactness)
  600. {
  601. int sz = m_width*m_height;
  602. const int numk = kseedsl.size();
  603. //int numitr(0);
  604. //----------------
  605. int offset = STEP;
  606. //if(STEP < 8) offset = STEP*1.5;//to prevent a crash due to a very small step size
  607. //----------------
  608. vector<double> clustersize(numk, 0);
  609. vector<double> inv(numk, 0);//to store 1/clustersize[k] values
  610. vector<double> sigmal(numk, 0);
  611. vector<double> sigmaa(numk, 0);
  612. vector<double> sigmab(numk, 0);
  613. vector<double> sigmax(numk, 0);
  614. vector<double> sigmay(numk, 0);
  615. vector<double> sigmaz(numk, 0);
  616. vector< double > initdouble(sz, DBL_MAX);
  617. vector< vector<double> > distvec(m_depth, initdouble);
  618. //vector<double> distvec(sz, DBL_MAX);
  619. double invwt = 1.0/((STEP/compactness)*(STEP/compactness));//compactness = 20.0 is usually good.
  620. int x1, y1, x2, y2, z1, z2;
  621. double l, a, b;
  622. double dist;
  623. double distxyz;
  624. for ( int itr = 0; itr < 5; itr++ )
  625. {
  626. distvec.assign(m_depth, initdouble);
  627. for ( int n = 0; n < numk; n++ )
  628. {
  629. y1 = max(0.0, kseedsy[n]-offset);
  630. y2 = min((double)m_height, kseedsy[n]+offset);
  631. x1 = max(0.0, kseedsx[n]-offset);
  632. x2 = min((double)m_width, kseedsx[n]+offset);
  633. z1 = max(0.0, kseedsz[n]-offset);
  634. z2 = min((double)m_depth, kseedsz[n]+offset);
  635. for ( int z = z1; z < z2; z++ )
  636. {
  637. for ( int y = y1; y < y2; y++ )
  638. {
  639. for ( int x = x1; x < x2; x++ )
  640. {
  641. int i = y*m_width + x;
  642. l = m_lvecvec[z][i];
  643. a = m_avecvec[z][i];
  644. b = m_bvecvec[z][i];
  645. dist = (l - kseedsl[n])*(l - kseedsl[n]) +
  646. (a - kseedsa[n])*(a - kseedsa[n]) +
  647. (b - kseedsb[n])*(b - kseedsb[n]);
  648. distxyz = (x - kseedsx[n])*(x - kseedsx[n]) +
  649. (y - kseedsy[n])*(y - kseedsy[n]) +
  650. (z - kseedsz[n])*(z - kseedsz[n]);
  651. //------------------------------------------------------------------------
  652. dist += distxyz*invwt;
  653. //------------------------------------------------------------------------
  654. if ( dist < distvec[z][i] )
  655. {
  656. distvec[z][i] = dist;
  657. klabels[z][i] = n;
  658. }
  659. }
  660. }
  661. }
  662. }
  663. //-----------------------------------------------------------------
  664. // Recalculate the centroid and store in the seed values
  665. //-----------------------------------------------------------------
  666. //instead of reassigning memory on each iteration, just reset.
  667. sigmal.assign(numk, 0);
  668. sigmaa.assign(numk, 0);
  669. sigmab.assign(numk, 0);
  670. sigmax.assign(numk, 0);
  671. sigmay.assign(numk, 0);
  672. sigmaz.assign(numk, 0);
  673. clustersize.assign(numk, 0);
  674. for ( int d = 0; d < m_depth; d++ )
  675. {
  676. int ind(0);
  677. for ( int r = 0; r < m_height; r++ )
  678. {
  679. for ( int c = 0; c < m_width; c++ )
  680. {
  681. sigmal[klabels[d][ind]] += m_lvecvec[d][ind];
  682. sigmaa[klabels[d][ind]] += m_avecvec[d][ind];
  683. sigmab[klabels[d][ind]] += m_bvecvec[d][ind];
  684. sigmax[klabels[d][ind]] += c;
  685. sigmay[klabels[d][ind]] += r;
  686. sigmaz[klabels[d][ind]] += d;
  687. clustersize[klabels[d][ind]] += 1.0;
  688. ind++;
  689. }
  690. }
  691. }
  692. {
  693. for ( int k = 0; k < numk; k++ )
  694. {
  695. if ( clustersize[k] <= 0 ) clustersize[k] = 1;
  696. inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
  697. }
  698. }
  699. {
  700. for ( int k = 0; k < numk; k++ )
  701. {
  702. kseedsl[k] = sigmal[k]*inv[k];
  703. kseedsa[k] = sigmaa[k]*inv[k];
  704. kseedsb[k] = sigmab[k]*inv[k];
  705. kseedsx[k] = sigmax[k]*inv[k];
  706. kseedsy[k] = sigmay[k]*inv[k];
  707. kseedsz[k] = sigmaz[k]*inv[k];
  708. }
  709. }
  710. }
  711. }
  712. //===========================================================================
  713. /// SaveSuperpixelLabels
  714. ///
  715. /// Save labels in raster scan order.
  716. //===========================================================================
  717. void SLIC::SaveSuperpixelLabels(
  718. const int*& labels,
  719. const int& width,
  720. const int& height,
  721. const string& filename,
  722. const string& path)
  723. {
  724. #ifdef WINDOWS
  725. char fname[256];
  726. char extn[256];
  727. _splitpath(filename.c_str(), NULL, NULL, fname, extn);
  728. string temp = fname;
  729. string finalpath = path + temp + string(".dat");
  730. #else
  731. string nameandextension = filename;
  732. size_t pos = filename.find_last_of("/");
  733. if (pos != string::npos)//if a slash is found, then take the filename with extension
  734. {
  735. nameandextension = filename.substr(pos+1);
  736. }
  737. string newname = nameandextension.replace(nameandextension.rfind(".")+1, 3, "dat");//find the position of the dot and replace the 3 characters following it.
  738. string finalpath = path+newname;
  739. #endif
  740. int sz = width*height;
  741. ofstream outfile;
  742. outfile.open(finalpath.c_str(), ios::binary);
  743. for ( int i = 0; i < sz; i++ )
  744. {
  745. outfile.write((const char*)&labels[i], sizeof(int));
  746. }
  747. outfile.close();
  748. }
  749. //===========================================================================
  750. /// SaveSupervoxelLabels
  751. ///
  752. /// Save labels in raster scan order.
  753. //===========================================================================
  754. void SLIC::SaveSupervoxelLabels(
  755. const int**& labels,
  756. const int& width,
  757. const int& height,
  758. const int& depth,
  759. const string& filename,
  760. const string& path)
  761. {
  762. #ifdef WINDOWS
  763. char fname[256];
  764. char extn[256];
  765. _splitpath(filename.c_str(), NULL, NULL, fname, extn);
  766. string temp = fname;
  767. string finalpath = path + temp + string(".dat");
  768. #else
  769. string nameandextension = filename;
  770. size_t pos = filename.find_last_of("/");
  771. if (pos != string::npos)//if a slash is found, then take the filename with extension
  772. {
  773. nameandextension = filename.substr(pos+1);
  774. }
  775. string newname = nameandextension.replace(nameandextension.rfind(".")+1, 3, "dat");//find the position of the dot and replace the 3 characters following it.
  776. string finalpath = path+newname;
  777. #endif
  778. int sz = width*height;
  779. ofstream outfile;
  780. outfile.open(finalpath.c_str(), ios::binary);
  781. for ( int d = 0; d < depth; d++ )
  782. {
  783. for ( int i = 0; i < sz; i++ )
  784. {
  785. outfile.write((const char*)&labels[d][i], sizeof(int));
  786. }
  787. }
  788. outfile.close();
  789. }
  790. //===========================================================================
  791. /// EnforceLabelConnectivity
  792. ///
  793. /// 1. finding an adjacent label for each new component at the start
  794. /// 2. if a certain component is too small, assigning the previously found
  795. /// adjacent label to this component, and not incrementing the label.
  796. //===========================================================================
  797. void SLIC::EnforceLabelConnectivity(
  798. const int* labels,//input labels that need to be corrected to remove stray labels
  799. const int width,
  800. const int height,
  801. int*& nlabels,//new labels
  802. int& numlabels,//the number of labels changes in the end if segments are removed
  803. const int& K) //the number of superpixels desired by the user
  804. {
  805. // const int dx8[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
  806. // const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1, 1};
  807. const int dx4[4] = {-1, 0, 1, 0};
  808. const int dy4[4] = { 0, -1, 0, 1};
  809. const int sz = width*height;
  810. const int SUPSZ = sz/K;
  811. //nlabels.resize(sz, -1);
  812. for ( int i = 0; i < sz; i++ ) nlabels[i] = -1;
  813. int label(0);
  814. int* xvec = new int[sz];
  815. int* yvec = new int[sz];
  816. int oindex(0);
  817. int adjlabel(0);//adjacent label
  818. for ( int j = 0; j < height; j++ )
  819. {
  820. for ( int k = 0; k < width; k++ )
  821. {
  822. if ( 0 > nlabels[oindex] )
  823. {
  824. nlabels[oindex] = label;
  825. //--------------------
  826. // Start a new segment
  827. //--------------------
  828. xvec[0] = k;
  829. yvec[0] = j;
  830. //-------------------------------------------------------
  831. // Quickly find an adjacent label for use later if needed
  832. //-------------------------------------------------------
  833. {
  834. for ( int n = 0; n < 4; n++ )
  835. {
  836. int x = xvec[0] + dx4[n];
  837. int y = yvec[0] + dy4[n];
  838. if ( (x >= 0 && x < width) && (y >= 0 && y < height) )
  839. {
  840. int nindex = y*width + x;
  841. if (nlabels[nindex] >= 0) adjlabel = nlabels[nindex];
  842. }
  843. }
  844. }
  845. int count(1);
  846. for ( int c = 0; c < count; c++ )
  847. {
  848. for ( int n = 0; n < 4; n++ )
  849. {
  850. int x = xvec[c] + dx4[n];
  851. int y = yvec[c] + dy4[n];
  852. if ( (x >= 0 && x < width) && (y >= 0 && y < height) )
  853. {
  854. int nindex = y*width + x;
  855. if ( 0 > nlabels[nindex] && labels[oindex] == labels[nindex] )
  856. {
  857. xvec[count] = x;
  858. yvec[count] = y;
  859. nlabels[nindex] = label;
  860. count++;
  861. }
  862. }
  863. }
  864. }
  865. //-------------------------------------------------------
  866. // If segment size is less then a limit, assign an
  867. // adjacent label found before, and decrement label count.
  868. //-------------------------------------------------------
  869. if (count <= SUPSZ >> 2)
  870. {
  871. for ( int c = 0; c < count; c++ )
  872. {
  873. int ind = yvec[c]*width+xvec[c];
  874. nlabels[ind] = adjlabel;
  875. }
  876. label--;
  877. }
  878. label++;
  879. }
  880. oindex++;
  881. }
  882. }
  883. numlabels = label;
  884. if (xvec) delete [] xvec;
  885. if (yvec) delete [] yvec;
  886. }
  887. //===========================================================================
  888. /// RelabelStraySupervoxels
  889. //===========================================================================
  890. void SLIC::EnforceSupervoxelLabelConnectivity(
  891. int**& labels,//input - previous labels, output - new labels
  892. const int& width,
  893. const int& height,
  894. const int& depth,
  895. int& numlabels,
  896. const int& STEP)
  897. {
  898. const int dx10[10] = {-1, 0, 1, 0, -1, 1, 1, -1, 0, 0};
  899. const int dy10[10] = { 0, -1, 0, 1, -1, -1, 1, 1, 0, 0};
  900. const int dz10[10] = { 0, 0, 0, 0, 0, 0, 0, 0, -1, 1};
  901. int sz = width*height;
  902. const int SUPSZ = STEP*STEP*STEP;
  903. int adjlabel(0);//adjacent label
  904. int* xvec = new int[SUPSZ*10];//a large enough size
  905. int* yvec = new int[SUPSZ*10];//a large enough size
  906. int* zvec = new int[SUPSZ*10];//a large enough size
  907. //------------------
  908. // memory allocation
  909. //------------------
  910. int** nlabels = new int*[depth];
  911. {
  912. for ( int d = 0; d < depth; d++ )
  913. {
  914. nlabels[d] = new int[sz];
  915. for ( int i = 0; i < sz; i++ ) nlabels[d][i] = -1;
  916. }
  917. }
  918. //------------------
  919. // labeling
  920. //------------------
  921. int lab(0);
  922. {
  923. for ( int d = 0; d < depth; d++ )
  924. {
  925. int i(0);
  926. for ( int h = 0; h < height; h++ )
  927. {
  928. for ( int w = 0; w < width; w++ )
  929. {
  930. if (nlabels[d][i] < 0)
  931. {
  932. nlabels[d][i] = lab;
  933. //-------------------------------------------------------
  934. // Quickly find an adjacent label for use later if needed
  935. //-------------------------------------------------------
  936. {
  937. for ( int n = 0; n < 10; n++ )
  938. {
  939. int x = w + dx10[n];
  940. int y = h + dy10[n];
  941. int z = d + dz10[n];
  942. if ( (x >= 0 && x < width) && (y >= 0 && y < height) && (z >= 0 && z < depth) )
  943. {
  944. int nindex = y*width + x;
  945. if (nlabels[z][nindex] >= 0)
  946. {
  947. adjlabel = nlabels[z][nindex];
  948. }
  949. }
  950. }
  951. }
  952. xvec[0] = w;
  953. yvec[0] = h;
  954. zvec[0] = d;
  955. int count(1);
  956. for ( int c = 0; c < count; c++ )
  957. {
  958. for ( int n = 0; n < 10; n++ )
  959. {
  960. int x = xvec[c] + dx10[n];
  961. int y = yvec[c] + dy10[n];
  962. int z = zvec[c] + dz10[n];
  963. if ( (x >= 0 && x < width) && (y >= 0 && y < height) && (z >= 0 && z < depth))
  964. {
  965. int nindex = y*width + x;
  966. if ( 0 > nlabels[z][nindex] && labels[d][i] == labels[z][nindex] )
  967. {
  968. xvec[count] = x;
  969. yvec[count] = y;
  970. zvec[count] = z;
  971. nlabels[z][nindex] = lab;
  972. count++;
  973. }
  974. }
  975. }
  976. }
  977. //-------------------------------------------------------
  978. // If segment size is less then a limit, assign an
  979. // adjacent label found before, and decrement label count.
  980. //-------------------------------------------------------
  981. if (count <= (SUPSZ >> 2))//this threshold can be changed according to needs
  982. {
  983. for ( int c = 0; c < count; c++ )
  984. {
  985. int ind = yvec[c]*width+xvec[c];
  986. nlabels[zvec[c]][ind] = adjlabel;
  987. }
  988. lab--;
  989. }
  990. //--------------------------------------------------------
  991. lab++;
  992. }
  993. i++;
  994. }
  995. }
  996. }
  997. }
  998. //------------------
  999. // mem de-allocation
  1000. //------------------
  1001. {
  1002. for ( int d = 0; d < depth; d++ )
  1003. {
  1004. for ( int i = 0; i < sz; i++ ) labels[d][i] = nlabels[d][i];
  1005. }
  1006. }
  1007. {
  1008. for ( int d = 0; d < depth; d++ )
  1009. {
  1010. delete [] nlabels[d];
  1011. }
  1012. }
  1013. delete [] nlabels;
  1014. //------------------
  1015. if (xvec) delete [] xvec;
  1016. if (yvec) delete [] yvec;
  1017. if (zvec) delete [] zvec;
  1018. //------------------
  1019. numlabels = lab;
  1020. //------------------
  1021. }
  1022. //===========================================================================
  1023. /// DoSuperpixelSegmentation_ForGivenSuperpixelSize
  1024. ///
  1025. /// The input parameter ubuff conains RGB values in a 32-bit unsigned integers
  1026. /// as follows:
  1027. ///
  1028. /// [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1]
  1029. ///
  1030. /// Nothing R G B
  1031. ///
  1032. /// The RGB values are accessed from (and packed into) the unsigned integers
  1033. /// using bitwise operators as can be seen in the function DoRGBtoLABConversion().
  1034. ///
  1035. /// compactness value depends on the input pixels values. For instance, if
  1036. /// the input is greyscale with values ranging from 0-100, then a compactness
  1037. /// value of 20.0 would give good results. A greater value will make the
  1038. /// superpixels more compact while a smaller value would make them more uneven.
  1039. ///
  1040. /// The labels can be saved if needed using SaveSuperpixelLabels()
  1041. //===========================================================================
  1042. void SLIC::DoSuperpixelSegmentation_ForGivenSuperpixelSize(
  1043. const unsigned int* ubuff,
  1044. const int width,
  1045. const int height,
  1046. int*& klabels,
  1047. int& numlabels,
  1048. const int& superpixelsize,
  1049. const double& compactness)
  1050. {
  1051. //------------------------------------------------
  1052. const int STEP = sqrt(double(superpixelsize))+0.5;
  1053. //------------------------------------------------
  1054. vector<double> kseedsl(0);
  1055. vector<double> kseedsa(0);
  1056. vector<double> kseedsb(0);
  1057. vector<double> kseedsx(0);
  1058. vector<double> kseedsy(0);
  1059. //--------------------------------------------------
  1060. m_width = width;
  1061. m_height = height;
  1062. int sz = m_width*m_height;
  1063. //klabels.resize( sz, -1 );
  1064. //--------------------------------------------------
  1065. klabels = new int[sz];
  1066. for ( int s = 0; s < sz; s++ ) klabels[s] = -1;
  1067. //--------------------------------------------------
  1068. if (1)//LAB, the default option
  1069. {
  1070. DoRGBtoLABConversion(ubuff, m_lvec, m_avec, m_bvec);
  1071. }
  1072. else//RGB
  1073. {
  1074. m_lvec = new double[sz];
  1075. m_avec = new double[sz];
  1076. m_bvec = new double[sz];
  1077. for ( int i = 0; i < sz; i++ )
  1078. {
  1079. m_lvec[i] = ubuff[i] >> 16 & 0xff;
  1080. m_avec[i] = ubuff[i] >> 8 & 0xff;
  1081. m_bvec[i] = ubuff[i] & 0xff;
  1082. }
  1083. }
  1084. //--------------------------------------------------
  1085. bool perturbseeds(false);//perturb seeds is not absolutely necessary, one can set this flag to false
  1086. vector<double> edgemag(0);
  1087. if (perturbseeds) DetectLabEdges(m_lvec, m_avec, m_bvec, m_width, m_height, edgemag);
  1088. GetLABXYSeeds_ForGivenStepSize(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, STEP, perturbseeds, edgemag);
  1089. PerformSuperpixelSLIC(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, klabels, STEP, edgemag,compactness);
  1090. numlabels = kseedsl.size();
  1091. int* nlabels = new int[sz];
  1092. EnforceLabelConnectivity(klabels, m_width, m_height, nlabels, numlabels, double(sz)/double(STEP*STEP));
  1093. {
  1094. for (int i = 0; i < sz; i++ ) klabels[i] = nlabels[i];
  1095. }
  1096. if (nlabels) delete [] nlabels;
  1097. }
  1098. //===========================================================================
  1099. /// DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels
  1100. ///
  1101. /// The input parameter ubuff conains RGB values in a 32-bit unsigned integers
  1102. /// as follows:
  1103. ///
  1104. /// [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1]
  1105. ///
  1106. /// Nothing R G B
  1107. ///
  1108. /// The RGB values are accessed from (and packed into) the unsigned integers
  1109. /// using bitwise operators as can be seen in the function DoRGBtoLABConversion().
  1110. ///
  1111. /// compactness value depends on the input pixels values. For instance, if
  1112. /// the input is greyscale with values ranging from 0-100, then a compactness
  1113. /// value of 20.0 would give good results. A greater value will make the
  1114. /// superpixels more compact while a smaller value would make them more uneven.
  1115. ///
  1116. /// The labels can be saved if needed using SaveSuperpixelLabels()
  1117. //===========================================================================
  1118. void SLIC::DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels(
  1119. const unsigned int* ubuff,
  1120. const int width,
  1121. const int height,
  1122. int*& klabels,
  1123. int& numlabels,
  1124. const int& K,//required number of superpixels
  1125. const double& compactness)//weight given to spatial distance
  1126. {
  1127. const int superpixelsize = 0.5+double(width*height)/double(K);
  1128. DoSuperpixelSegmentation_ForGivenSuperpixelSize(ubuff,width,height,klabels,numlabels,superpixelsize,compactness);
  1129. }
  1130. //===========================================================================
  1131. /// DoSupervoxelSegmentation
  1132. ///
  1133. /// There is option to save the labels if needed.
  1134. ///
  1135. /// The input parameter ubuffvec holds all the video frames. It is a
  1136. /// 2-dimensional array. The first dimension is depth and the second dimension
  1137. /// is pixel location in a frame. For example, to access a pixel in the 3rd
  1138. /// frame (i.e. depth index 2), in the 4th row (i.e. height index 3) on the
  1139. /// 37th column (i.e. width index 36), you would write:
  1140. ///
  1141. /// unsigned int the_pixel_i_want = ubuffvec[2][3*width + 36]
  1142. ///
  1143. /// In addition, here is how the RGB values are contained in a 32-bit unsigned
  1144. /// integer:
  1145. ///
  1146. /// [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1]
  1147. ///
  1148. /// Nothing R G B
  1149. ///
  1150. /// The RGB values are accessed from (and packed into) the unsigned integers
  1151. /// using bitwise operators as can be seen in the function DoRGBtoLABConversion().
  1152. ///
  1153. /// compactness value depends on the input pixels values. For instance, if
  1154. /// the input is greyscale with values ranging from 0-100, then a compactness
  1155. /// value of 20.0 would give good results. A greater value will make the
  1156. /// supervoxels more compact while a smaller value would make them more uneven.
  1157. //===========================================================================
  1158. void SLIC::DoSupervoxelSegmentation(
  1159. unsigned int**& ubuffvec,
  1160. const int& width,
  1161. const int& height,
  1162. const int& depth,
  1163. int**& klabels,
  1164. int& numlabels,
  1165. const int& supervoxelsize,
  1166. const double& compactness)
  1167. {
  1168. //---------------------------------------------------------
  1169. const int STEP = 0.5 + pow(double(supervoxelsize),1.0/3.0);
  1170. //---------------------------------------------------------
  1171. vector<double> kseedsl(0);
  1172. vector<double> kseedsa(0);
  1173. vector<double> kseedsb(0);
  1174. vector<double> kseedsx(0);
  1175. vector<double> kseedsy(0);
  1176. vector<double> kseedsz(0);
  1177. //--------------------------------------------------
  1178. m_width = width;
  1179. m_height = height;
  1180. m_depth = depth;
  1181. int sz = m_width*m_height;
  1182. //--------------------------------------------------
  1183. //klabels = new int*[depth];
  1184. m_lvecvec = new double*[depth];
  1185. m_avecvec = new double*[depth];
  1186. m_bvecvec = new double*[depth];
  1187. for ( int d = 0; d < depth; d++ )
  1188. {
  1189. //klabels[d] = new int[sz];
  1190. m_lvecvec[d] = new double[sz];
  1191. m_avecvec[d] = new double[sz];
  1192. m_bvecvec[d] = new double[sz];
  1193. for ( int s = 0; s < sz; s++ )
  1194. {
  1195. klabels[d][s] = -1;
  1196. }
  1197. }
  1198. DoRGBtoLABConversion(ubuffvec, m_lvecvec, m_avecvec, m_bvecvec);
  1199. GetKValues_LABXYZ(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, kseedsz, STEP);
  1200. PerformSupervoxelSLIC(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, kseedsz, klabels, STEP, compactness);
  1201. EnforceSupervoxelLabelConnectivity(klabels, width, height, depth, numlabels, STEP);
  1202. }